From 222e2a7620e6520ffaf4fc4e69d79c18da31542e Mon Sep 17 00:00:00 2001
From: "Zancanaro; Carlo" <czan8762@plang3.cs.usyd.edu.au>
Date: Mon, 24 Sep 2012 09:58:17 +1000
Subject: Add the clang library to the repo (with some of my changes, too).

---
 clang/unittests/Basic/FileManagerTest.cpp          | 223 ++++++++++++++++
 clang/unittests/Basic/Makefile                     |  15 ++
 clang/unittests/Basic/SourceManagerTest.cpp        | 296 +++++++++++++++++++++
 clang/unittests/CMakeLists.txt                     |  73 +++++
 clang/unittests/Frontend/FrontendActionTest.cpp    |  74 ++++++
 clang/unittests/Frontend/Makefile                  |  19 ++
 clang/unittests/Lex/LexerTest.cpp                  | 177 ++++++++++++
 clang/unittests/Lex/Makefile                       |  15 ++
 clang/unittests/Lex/PreprocessingRecordTest.cpp    | 139 ++++++++++
 clang/unittests/Makefile                           |  28 ++
 .../unittests/Tooling/CompilationDatabaseTest.cpp  | 292 ++++++++++++++++++++
 clang/unittests/Tooling/Makefile                   |  17 ++
 clang/unittests/Tooling/ToolingTest.cpp            | 113 ++++++++
 13 files changed, 1481 insertions(+)
 create mode 100644 clang/unittests/Basic/FileManagerTest.cpp
 create mode 100644 clang/unittests/Basic/Makefile
 create mode 100644 clang/unittests/Basic/SourceManagerTest.cpp
 create mode 100644 clang/unittests/CMakeLists.txt
 create mode 100644 clang/unittests/Frontend/FrontendActionTest.cpp
 create mode 100644 clang/unittests/Frontend/Makefile
 create mode 100644 clang/unittests/Lex/LexerTest.cpp
 create mode 100644 clang/unittests/Lex/Makefile
 create mode 100644 clang/unittests/Lex/PreprocessingRecordTest.cpp
 create mode 100644 clang/unittests/Makefile
 create mode 100644 clang/unittests/Tooling/CompilationDatabaseTest.cpp
 create mode 100644 clang/unittests/Tooling/Makefile
 create mode 100644 clang/unittests/Tooling/ToolingTest.cpp

(limited to 'clang/unittests')

diff --git a/clang/unittests/Basic/FileManagerTest.cpp b/clang/unittests/Basic/FileManagerTest.cpp
new file mode 100644
index 0000000..91998b6
--- /dev/null
+++ b/clang/unittests/Basic/FileManagerTest.cpp
@@ -0,0 +1,223 @@
+//===- unittests/Basic/FileMangerTest.cpp ------------ FileManger tests ---===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/FileSystemOptions.h"
+#include "clang/Basic/FileSystemStatCache.h"
+#include "clang/Basic/FileManager.h"
+
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace clang;
+
+namespace {
+
+// Used to create a fake file system for running the tests with such
+// that the tests are not affected by the structure/contents of the
+// file system on the machine running the tests.
+class FakeStatCache : public FileSystemStatCache {
+private:
+  // Maps a file/directory path to its desired stat result.  Anything
+  // not in this map is considered to not exist in the file system.
+  llvm::StringMap<struct stat, llvm::BumpPtrAllocator> StatCalls;
+
+  void InjectFileOrDirectory(const char *Path, ino_t INode, bool IsFile) {
+    struct stat statBuf;
+    memset(&statBuf, 0, sizeof(statBuf));
+    statBuf.st_dev = 1;
+#ifndef _WIN32  // struct stat has no st_ino field on Windows.
+    statBuf.st_ino = INode;
+#endif
+    statBuf.st_mode = IsFile ? (0777 | S_IFREG)  // a regular file
+        : (0777 | S_IFDIR);  // a directory
+    StatCalls[Path] = statBuf;
+  }
+
+public:
+  // Inject a file with the given inode value to the fake file system.
+  void InjectFile(const char *Path, ino_t INode) {
+    InjectFileOrDirectory(Path, INode, /*IsFile=*/true);
+  }
+
+  // Inject a directory with the given inode value to the fake file system.
+  void InjectDirectory(const char *Path, ino_t INode) {
+    InjectFileOrDirectory(Path, INode, /*IsFile=*/false);
+  }
+
+  // Implement FileSystemStatCache::getStat().
+  virtual LookupResult getStat(const char *Path, struct stat &StatBuf,
+                               int *FileDescriptor) {
+    if (StatCalls.count(Path) != 0) {
+      StatBuf = StatCalls[Path];
+      return CacheExists;
+    }
+
+    return CacheMissing;  // This means the file/directory doesn't exist.
+  }
+};
+
+// The test fixture.
+class FileManagerTest : public ::testing::Test {
+ protected:
+  FileManagerTest() : manager(options) {
+  }
+
+  FileSystemOptions options;
+  FileManager manager;
+};
+
+// When a virtual file is added, its getDir() field is set correctly
+// (not NULL, correct name).
+TEST_F(FileManagerTest, getVirtualFileSetsTheDirFieldCorrectly) {
+  const FileEntry *file = manager.getVirtualFile("foo.cpp", 42, 0);
+  ASSERT_TRUE(file != NULL);
+
+  const DirectoryEntry *dir = file->getDir();
+  ASSERT_TRUE(dir != NULL);
+  EXPECT_STREQ(".", dir->getName());
+
+  file = manager.getVirtualFile("x/y/z.cpp", 42, 0);
+  ASSERT_TRUE(file != NULL);
+
+  dir = file->getDir();
+  ASSERT_TRUE(dir != NULL);
+  EXPECT_STREQ("x/y", dir->getName());
+}
+
+// Before any virtual file is added, no virtual directory exists.
+TEST_F(FileManagerTest, NoVirtualDirectoryExistsBeforeAVirtualFileIsAdded) {
+  // An empty FakeStatCache causes all stat calls made by the
+  // FileManager to report "file/directory doesn't exist".  This
+  // avoids the possibility of the result of this test being affected
+  // by what's in the real file system.
+  manager.addStatCache(new FakeStatCache);
+
+  EXPECT_EQ(NULL, manager.getDirectory("virtual/dir/foo"));
+  EXPECT_EQ(NULL, manager.getDirectory("virtual/dir"));
+  EXPECT_EQ(NULL, manager.getDirectory("virtual"));
+}
+
+// When a virtual file is added, all of its ancestors should be created.
+TEST_F(FileManagerTest, getVirtualFileCreatesDirectoryEntriesForAncestors) {
+  // Fake an empty real file system.
+  manager.addStatCache(new FakeStatCache);
+
+  manager.getVirtualFile("virtual/dir/bar.h", 100, 0);
+  EXPECT_EQ(NULL, manager.getDirectory("virtual/dir/foo"));
+
+  const DirectoryEntry *dir = manager.getDirectory("virtual/dir");
+  ASSERT_TRUE(dir != NULL);
+  EXPECT_STREQ("virtual/dir", dir->getName());
+
+  dir = manager.getDirectory("virtual");
+  ASSERT_TRUE(dir != NULL);
+  EXPECT_STREQ("virtual", dir->getName());
+}
+
+// getFile() returns non-NULL if a real file exists at the given path.
+TEST_F(FileManagerTest, getFileReturnsValidFileEntryForExistingRealFile) {
+  // Inject fake files into the file system.
+  FakeStatCache *statCache = new FakeStatCache;
+  statCache->InjectDirectory("/tmp", 42);
+  statCache->InjectFile("/tmp/test", 43);
+  manager.addStatCache(statCache);
+
+  const FileEntry *file = manager.getFile("/tmp/test");
+  ASSERT_TRUE(file != NULL);
+  EXPECT_STREQ("/tmp/test", file->getName());
+
+  const DirectoryEntry *dir = file->getDir();
+  ASSERT_TRUE(dir != NULL);
+  EXPECT_STREQ("/tmp", dir->getName());
+}
+
+// getFile() returns non-NULL if a virtual file exists at the given path.
+TEST_F(FileManagerTest, getFileReturnsValidFileEntryForExistingVirtualFile) {
+  // Fake an empty real file system.
+  manager.addStatCache(new FakeStatCache);
+
+  manager.getVirtualFile("virtual/dir/bar.h", 100, 0);
+  const FileEntry *file = manager.getFile("virtual/dir/bar.h");
+  ASSERT_TRUE(file != NULL);
+  EXPECT_STREQ("virtual/dir/bar.h", file->getName());
+
+  const DirectoryEntry *dir = file->getDir();
+  ASSERT_TRUE(dir != NULL);
+  EXPECT_STREQ("virtual/dir", dir->getName());
+}
+
+// getFile() returns different FileEntries for different paths when
+// there's no aliasing.
+TEST_F(FileManagerTest, getFileReturnsDifferentFileEntriesForDifferentFiles) {
+  // Inject two fake files into the file system.  Different inodes
+  // mean the files are not symlinked together.
+  FakeStatCache *statCache = new FakeStatCache;
+  statCache->InjectDirectory(".", 41);
+  statCache->InjectFile("foo.cpp", 42);
+  statCache->InjectFile("bar.cpp", 43);
+  manager.addStatCache(statCache);
+
+  const FileEntry *fileFoo = manager.getFile("foo.cpp");
+  const FileEntry *fileBar = manager.getFile("bar.cpp");
+  ASSERT_TRUE(fileFoo != NULL);
+  ASSERT_TRUE(fileBar != NULL);
+  EXPECT_NE(fileFoo, fileBar);
+}
+
+// getFile() returns NULL if neither a real file nor a virtual file
+// exists at the given path.
+TEST_F(FileManagerTest, getFileReturnsNULLForNonexistentFile) {
+  // Inject a fake foo.cpp into the file system.
+  FakeStatCache *statCache = new FakeStatCache;
+  statCache->InjectDirectory(".", 41);
+  statCache->InjectFile("foo.cpp", 42);
+  manager.addStatCache(statCache);
+
+  // Create a virtual bar.cpp file.
+  manager.getVirtualFile("bar.cpp", 200, 0);
+
+  const FileEntry *file = manager.getFile("xyz.txt");
+  EXPECT_EQ(NULL, file);
+}
+
+// The following tests apply to Unix-like system only.
+
+#ifndef _WIN32
+
+// getFile() returns the same FileEntry for real files that are aliases.
+TEST_F(FileManagerTest, getFileReturnsSameFileEntryForAliasedRealFiles) {
+  // Inject two real files with the same inode.
+  FakeStatCache *statCache = new FakeStatCache;
+  statCache->InjectDirectory("abc", 41);
+  statCache->InjectFile("abc/foo.cpp", 42);
+  statCache->InjectFile("abc/bar.cpp", 42);
+  manager.addStatCache(statCache);
+
+  EXPECT_EQ(manager.getFile("abc/foo.cpp"), manager.getFile("abc/bar.cpp"));
+}
+
+// getFile() returns the same FileEntry for virtual files that have
+// corresponding real files that are aliases.
+TEST_F(FileManagerTest, getFileReturnsSameFileEntryForAliasedVirtualFiles) {
+  // Inject two real files with the same inode.
+  FakeStatCache *statCache = new FakeStatCache;
+  statCache->InjectDirectory("abc", 41);
+  statCache->InjectFile("abc/foo.cpp", 42);
+  statCache->InjectFile("abc/bar.cpp", 42);
+  manager.addStatCache(statCache);
+
+  manager.getVirtualFile("abc/foo.cpp", 100, 0);
+  manager.getVirtualFile("abc/bar.cpp", 200, 0);
+
+  EXPECT_EQ(manager.getFile("abc/foo.cpp"), manager.getFile("abc/bar.cpp"));
+}
+
+#endif  // !_WIN32
+
+} // anonymous namespace
diff --git a/clang/unittests/Basic/Makefile b/clang/unittests/Basic/Makefile
new file mode 100644
index 0000000..82de790
--- /dev/null
+++ b/clang/unittests/Basic/Makefile
@@ -0,0 +1,15 @@
+##===- unittests/Basic/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 = ../..
+TESTNAME = Basic
+LINK_COMPONENTS := support mc
+USEDLIBS = clangLex.a clangBasic.a
+
+include $(CLANG_LEVEL)/unittests/Makefile
diff --git a/clang/unittests/Basic/SourceManagerTest.cpp b/clang/unittests/Basic/SourceManagerTest.cpp
new file mode 100644
index 0000000..429b58d
--- /dev/null
+++ b/clang/unittests/Basic/SourceManagerTest.cpp
@@ -0,0 +1,296 @@
+//===- unittests/Basic/SourceManagerTest.cpp ------ SourceManager tests ---===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/TargetOptions.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/ModuleLoader.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Config/config.h"
+
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace clang;
+
+namespace {
+
+// The test fixture.
+class SourceManagerTest : public ::testing::Test {
+protected:
+  SourceManagerTest()
+    : FileMgr(FileMgrOpts),
+      DiagID(new DiagnosticIDs()),
+      Diags(DiagID, new IgnoringDiagConsumer()),
+      SourceMgr(Diags, FileMgr) {
+    TargetOpts.Triple = "x86_64-apple-darwin11.1.0";
+    Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
+  }
+
+  FileSystemOptions FileMgrOpts;
+  FileManager FileMgr;
+  IntrusiveRefCntPtr<DiagnosticIDs> DiagID;
+  DiagnosticsEngine Diags;
+  SourceManager SourceMgr;
+  LangOptions LangOpts;
+  TargetOptions TargetOpts;
+  IntrusiveRefCntPtr<TargetInfo> Target;
+};
+
+class VoidModuleLoader : public ModuleLoader {
+  virtual Module *loadModule(SourceLocation ImportLoc, ModuleIdPath Path,
+                             Module::NameVisibilityKind Visibility,
+                             bool IsInclusionDirective) {
+    return 0;
+  }
+};
+
+TEST_F(SourceManagerTest, isBeforeInTranslationUnit) {
+  const char *source =
+    "#define M(x) [x]\n"
+    "M(foo)";
+  MemoryBuffer *buf = MemoryBuffer::getMemBuffer(source);
+  FileID mainFileID = SourceMgr.createMainFileIDForMemBuffer(buf);
+
+  VoidModuleLoader ModLoader;
+  HeaderSearch HeaderInfo(FileMgr, Diags, LangOpts, &*Target);
+  Preprocessor PP(Diags, LangOpts,
+                  Target.getPtr(),
+                  SourceMgr, HeaderInfo, ModLoader,
+                  /*IILookup =*/ 0,
+                  /*OwnsHeaderSearch =*/false,
+                  /*DelayInitialization =*/ false);
+  PP.EnterMainSourceFile();
+
+  std::vector<Token> toks;
+  while (1) {
+    Token tok;
+    PP.Lex(tok);
+    if (tok.is(tok::eof))
+      break;
+    toks.push_back(tok);
+  }
+
+  // Make sure we got the tokens that we expected.
+  ASSERT_EQ(3U, toks.size());
+  ASSERT_EQ(tok::l_square, toks[0].getKind());
+  ASSERT_EQ(tok::identifier, toks[1].getKind());
+  ASSERT_EQ(tok::r_square, toks[2].getKind());
+  
+  SourceLocation lsqrLoc = toks[0].getLocation();
+  SourceLocation idLoc = toks[1].getLocation();
+  SourceLocation rsqrLoc = toks[2].getLocation();
+  
+  SourceLocation macroExpStartLoc = SourceMgr.translateLineCol(mainFileID, 2, 1);
+  SourceLocation macroExpEndLoc = SourceMgr.translateLineCol(mainFileID, 2, 6);
+  ASSERT_TRUE(macroExpStartLoc.isFileID());
+  ASSERT_TRUE(macroExpEndLoc.isFileID());
+
+  SmallString<32> str;
+  ASSERT_EQ("M", PP.getSpelling(macroExpStartLoc, str));
+  ASSERT_EQ(")", PP.getSpelling(macroExpEndLoc, str));
+
+  EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(lsqrLoc, idLoc));
+  EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(idLoc, rsqrLoc));
+  EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(macroExpStartLoc, idLoc));
+  EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(idLoc, macroExpEndLoc));
+}
+
+#if defined(LLVM_ON_UNIX)
+
+TEST_F(SourceManagerTest, getMacroArgExpandedLocation) {
+  const char *header =
+    "#define FM(x,y) x\n";
+
+  const char *main =
+    "#include \"/test-header.h\"\n"
+    "#define VAL 0\n"
+    "FM(VAL,0)\n"
+    "FM(0,VAL)\n"
+    "FM(FM(0,VAL),0)\n"
+    "#define CONCAT(X, Y) X##Y\n"
+    "CONCAT(1,1)\n";
+
+  MemoryBuffer *headerBuf = MemoryBuffer::getMemBuffer(header);
+  MemoryBuffer *mainBuf = MemoryBuffer::getMemBuffer(main);
+  FileID mainFileID = SourceMgr.createMainFileIDForMemBuffer(mainBuf);
+
+  const FileEntry *headerFile = FileMgr.getVirtualFile("/test-header.h",
+                                                 headerBuf->getBufferSize(), 0);
+  SourceMgr.overrideFileContents(headerFile, headerBuf);
+
+  VoidModuleLoader ModLoader;
+  HeaderSearch HeaderInfo(FileMgr, Diags, LangOpts, &*Target);
+  Preprocessor PP(Diags, LangOpts,
+                  Target.getPtr(),
+                  SourceMgr, HeaderInfo, ModLoader,
+                  /*IILookup =*/ 0,
+                  /*OwnsHeaderSearch =*/false,
+                  /*DelayInitialization =*/ false);
+  PP.EnterMainSourceFile();
+
+  std::vector<Token> toks;
+  while (1) {
+    Token tok;
+    PP.Lex(tok);
+    if (tok.is(tok::eof))
+      break;
+    toks.push_back(tok);
+  }
+
+  // Make sure we got the tokens that we expected.
+  ASSERT_EQ(4U, toks.size());
+  ASSERT_EQ(tok::numeric_constant, toks[0].getKind());
+  ASSERT_EQ(tok::numeric_constant, toks[1].getKind());
+  ASSERT_EQ(tok::numeric_constant, toks[2].getKind());
+  ASSERT_EQ(tok::numeric_constant, toks[3].getKind());
+
+  SourceLocation defLoc = SourceMgr.translateLineCol(mainFileID, 2, 13);
+  SourceLocation loc1 = SourceMgr.translateLineCol(mainFileID, 3, 8);
+  SourceLocation loc2 = SourceMgr.translateLineCol(mainFileID, 4, 4);
+  SourceLocation loc3 = SourceMgr.translateLineCol(mainFileID, 5, 7);
+  SourceLocation defLoc2 = SourceMgr.translateLineCol(mainFileID, 6, 22);
+  defLoc = SourceMgr.getMacroArgExpandedLocation(defLoc);
+  loc1 = SourceMgr.getMacroArgExpandedLocation(loc1);
+  loc2 = SourceMgr.getMacroArgExpandedLocation(loc2);
+  loc3 = SourceMgr.getMacroArgExpandedLocation(loc3);
+  defLoc2 = SourceMgr.getMacroArgExpandedLocation(defLoc2);
+
+  EXPECT_TRUE(defLoc.isFileID());
+  EXPECT_TRUE(loc1.isFileID());
+  EXPECT_TRUE(SourceMgr.isMacroArgExpansion(loc2));
+  EXPECT_TRUE(SourceMgr.isMacroArgExpansion(loc3));
+  EXPECT_EQ(loc2, toks[1].getLocation());
+  EXPECT_EQ(loc3, toks[2].getLocation());
+  EXPECT_TRUE(defLoc2.isFileID());
+}
+
+namespace {
+
+struct MacroAction {
+  SourceLocation Loc;
+  std::string Name;
+  bool isDefinition; // if false, it is expansion.
+  
+  MacroAction(SourceLocation Loc, StringRef Name, bool isDefinition)
+    : Loc(Loc), Name(Name), isDefinition(isDefinition) { }
+};
+
+class MacroTracker : public PPCallbacks {
+  std::vector<MacroAction> &Macros;
+
+public:
+  explicit MacroTracker(std::vector<MacroAction> &Macros) : Macros(Macros) { }
+  
+  virtual void MacroDefined(const Token &MacroNameTok, const MacroInfo *MI) {
+    Macros.push_back(MacroAction(MI->getDefinitionLoc(),
+                                 MacroNameTok.getIdentifierInfo()->getName(),
+                                 true));
+  }
+  virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo* MI,
+                            SourceRange Range) {
+    Macros.push_back(MacroAction(MacroNameTok.getLocation(),
+                                 MacroNameTok.getIdentifierInfo()->getName(),
+                                 false));
+  }
+};
+
+}
+
+TEST_F(SourceManagerTest, isBeforeInTranslationUnitWithMacroInInclude) {
+  const char *header =
+    "#define MACRO_IN_INCLUDE 0\n";
+
+  const char *main =
+    "#define M(x) x\n"
+    "#define INC \"/test-header.h\"\n"
+    "#include M(INC)\n"
+    "#define INC2 </test-header.h>\n"
+    "#include M(INC2)\n";
+
+  MemoryBuffer *headerBuf = MemoryBuffer::getMemBuffer(header);
+  MemoryBuffer *mainBuf = MemoryBuffer::getMemBuffer(main);
+  SourceMgr.createMainFileIDForMemBuffer(mainBuf);
+
+  const FileEntry *headerFile = FileMgr.getVirtualFile("/test-header.h",
+                                                 headerBuf->getBufferSize(), 0);
+  SourceMgr.overrideFileContents(headerFile, headerBuf);
+
+  VoidModuleLoader ModLoader;
+  HeaderSearch HeaderInfo(FileMgr, Diags, LangOpts, &*Target);
+  Preprocessor PP(Diags, LangOpts,
+                  Target.getPtr(),
+                  SourceMgr, HeaderInfo, ModLoader,
+                  /*IILookup =*/ 0,
+                  /*OwnsHeaderSearch =*/false,
+                  /*DelayInitialization =*/ false);
+
+  std::vector<MacroAction> Macros;
+  PP.addPPCallbacks(new MacroTracker(Macros));
+
+  PP.EnterMainSourceFile();
+
+  std::vector<Token> toks;
+  while (1) {
+    Token tok;
+    PP.Lex(tok);
+    if (tok.is(tok::eof))
+      break;
+    toks.push_back(tok);
+  }
+
+  // Make sure we got the tokens that we expected.
+  ASSERT_EQ(0U, toks.size());
+
+  ASSERT_EQ(9U, Macros.size());
+  // #define M(x) x
+  ASSERT_TRUE(Macros[0].isDefinition);
+  ASSERT_EQ("M", Macros[0].Name);
+  // #define INC "/test-header.h"
+  ASSERT_TRUE(Macros[1].isDefinition);
+  ASSERT_EQ("INC", Macros[1].Name);
+  // M expansion in #include M(INC)
+  ASSERT_FALSE(Macros[2].isDefinition);
+  ASSERT_EQ("M", Macros[2].Name);
+  // INC expansion in #include M(INC)
+  ASSERT_FALSE(Macros[3].isDefinition);
+  ASSERT_EQ("INC", Macros[3].Name);
+  // #define MACRO_IN_INCLUDE 0
+  ASSERT_TRUE(Macros[4].isDefinition);
+  ASSERT_EQ("MACRO_IN_INCLUDE", Macros[4].Name);
+  // #define INC2 </test-header.h>
+  ASSERT_TRUE(Macros[5].isDefinition);
+  ASSERT_EQ("INC2", Macros[5].Name);
+  // M expansion in #include M(INC2)
+  ASSERT_FALSE(Macros[6].isDefinition);
+  ASSERT_EQ("M", Macros[6].Name);
+  // INC2 expansion in #include M(INC2)
+  ASSERT_FALSE(Macros[7].isDefinition);
+  ASSERT_EQ("INC2", Macros[7].Name);
+  // #define MACRO_IN_INCLUDE 0
+  ASSERT_TRUE(Macros[8].isDefinition);
+  ASSERT_EQ("MACRO_IN_INCLUDE", Macros[8].Name);
+
+  // The INC expansion in #include M(INC) comes before the first
+  // MACRO_IN_INCLUDE definition of the included file.
+  EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(Macros[3].Loc, Macros[4].Loc));
+
+  // The INC2 expansion in #include M(INC2) comes before the second
+  // MACRO_IN_INCLUDE definition of the included file.
+  EXPECT_TRUE(SourceMgr.isBeforeInTranslationUnit(Macros[7].Loc, Macros[8].Loc));
+}
+
+#endif
+
+} // anonymous namespace
diff --git a/clang/unittests/CMakeLists.txt b/clang/unittests/CMakeLists.txt
new file mode 100644
index 0000000..0b3eac9
--- /dev/null
+++ b/clang/unittests/CMakeLists.txt
@@ -0,0 +1,73 @@
+include(LLVMParseArguments)
+
+# add_clang_unittest(test_dirname file1.cpp file2.cpp ...
+#                    [USED_LIBS lib1 lib2]
+#                    [LINK_COMPONENTS component1 component2])
+#
+# Will compile the list of files together and link against the clang
+# libraries in the USED_LIBS list and the llvm-config components in
+# the LINK_COMPONENTS list.  Produces a binary named
+# 'basename(test_dirname)Tests'.
+function(add_clang_unittest)
+  PARSE_ARGUMENTS(CLANG_UNITTEST "USED_LIBS;LINK_COMPONENTS" "" ${ARGN})
+  set(LLVM_LINK_COMPONENTS ${CLANG_UNITTEST_LINK_COMPONENTS})
+  set(LLVM_USED_LIBS ${CLANG_UNITTEST_USED_LIBS})
+  list(GET CLANG_UNITTEST_DEFAULT_ARGS 0 test_dirname)
+  list(REMOVE_AT CLANG_UNITTEST_DEFAULT_ARGS 0)
+
+  string(REGEX MATCH "([^/]+)$" test_name ${test_dirname})
+  if (CMAKE_BUILD_TYPE)
+    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY
+      ${CLANG_BINARY_DIR}/unittests/${test_dirname}/${CMAKE_BUILD_TYPE})
+  else()
+    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY
+      ${CLANG_BINARY_DIR}/unittests/${test_dirname})
+  endif()
+  if( NOT LLVM_BUILD_TESTS )
+    set(EXCLUDE_FROM_ALL ON)
+  endif()
+  add_clang_executable(${test_name}Tests ${CLANG_UNITTEST_DEFAULT_ARGS})
+  add_dependencies(ClangUnitTests ${test_name}Tests)
+  set_target_properties(${test_name}Tests PROPERTIES FOLDER "Clang tests")
+endfunction()
+
+add_custom_target(ClangUnitTests)
+set_target_properties(ClangUnitTests PROPERTIES FOLDER "Clang tests")
+
+include_directories(${LLVM_MAIN_SRC_DIR}/utils/unittest/googletest/include)
+add_definitions(-DGTEST_HAS_RTTI=0)
+if( LLVM_COMPILER_IS_GCC_COMPATIBLE )
+  llvm_replace_compiler_option(CMAKE_CXX_FLAGS "-frtti" "-fno-rtti")
+elseif( MSVC )
+  llvm_replace_compiler_option(CMAKE_CXX_FLAGS "/GR" "/GR-")
+endif()
+
+if (NOT LLVM_ENABLE_THREADS)
+  add_definitions(-DGTEST_HAS_PTHREAD=0)
+endif()
+
+if(SUPPORTS_NO_VARIADIC_MACROS_FLAG)
+  add_definitions("-Wno-variadic-macros")
+endif()
+
+add_clang_unittest(Basic
+  Basic/FileManagerTest.cpp
+  Basic/SourceManagerTest.cpp
+  USED_LIBS gtest gtest_main clangLex
+ )
+
+add_clang_unittest(Lex
+  Lex/LexerTest.cpp
+  USED_LIBS gtest gtest_main clangLex
+ )
+
+add_clang_unittest(Frontend
+  Frontend/FrontendActionTest.cpp
+  USED_LIBS gtest gtest_main clangFrontend
+ )
+
+add_clang_unittest(Tooling
+  Tooling/CompilationDatabaseTest.cpp
+  Tooling/ToolingTest.cpp
+  USED_LIBS gtest gtest_main clangTooling
+ )
diff --git a/clang/unittests/Frontend/FrontendActionTest.cpp b/clang/unittests/Frontend/FrontendActionTest.cpp
new file mode 100644
index 0000000..2d4befc
--- /dev/null
+++ b/clang/unittests/Frontend/FrontendActionTest.cpp
@@ -0,0 +1,74 @@
+//===- unittests/Frontend/FrontendActionTest.cpp - FrontendAction tests ---===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/FrontendAction.h"
+
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace clang;
+
+namespace {
+
+class TestASTFrontendAction : public ASTFrontendAction {
+public:
+  std::vector<std::string> decl_names;
+
+  virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
+                                         StringRef InFile) {
+    return new Visitor(decl_names);
+  }
+
+private:
+  class Visitor : public ASTConsumer, public RecursiveASTVisitor<Visitor> {
+  public:
+    Visitor(std::vector<std::string> &decl_names) : decl_names_(decl_names) {}
+
+    virtual void HandleTranslationUnit(ASTContext &context) {
+      TraverseDecl(context.getTranslationUnitDecl());
+    }
+
+    virtual bool VisitNamedDecl(NamedDecl *Decl) {
+      decl_names_.push_back(Decl->getQualifiedNameAsString());
+      return true;
+    }
+
+  private:
+    std::vector<std::string> &decl_names_;
+  };
+};
+
+TEST(ASTFrontendAction, Sanity) {
+  CompilerInvocation *invocation = new CompilerInvocation;
+  invocation->getPreprocessorOpts().addRemappedFile(
+    "test.cc", MemoryBuffer::getMemBuffer("int main() { float x; }"));
+  invocation->getFrontendOpts().Inputs.push_back(FrontendInputFile("test.cc",
+                                                                   IK_CXX));
+  invocation->getFrontendOpts().ProgramAction = frontend::ParseSyntaxOnly;
+  invocation->getTargetOpts().Triple = "i386-unknown-linux-gnu";
+  CompilerInstance compiler;
+  compiler.setInvocation(invocation);
+  compiler.createDiagnostics(0, NULL);
+
+  TestASTFrontendAction test_action;
+  ASSERT_TRUE(compiler.ExecuteAction(test_action));
+  ASSERT_EQ(3U, test_action.decl_names.size());
+  EXPECT_EQ("__builtin_va_list", test_action.decl_names[0]);
+  EXPECT_EQ("main", test_action.decl_names[1]);
+  EXPECT_EQ("x", test_action.decl_names[2]);
+}
+
+} // anonymous namespace
diff --git a/clang/unittests/Frontend/Makefile b/clang/unittests/Frontend/Makefile
new file mode 100644
index 0000000..f3e6396
--- /dev/null
+++ b/clang/unittests/Frontend/Makefile
@@ -0,0 +1,19 @@
+##===- unittests/Frontend/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 = ../..
+TESTNAME = Frontend
+LINK_COMPONENTS := support mc
+USEDLIBS = clangFrontendTool.a clangFrontend.a clangDriver.a \
+           clangSerialization.a clangCodeGen.a clangParse.a clangSema.a \
+           clangStaticAnalyzerCheckers.a clangStaticAnalyzerCore.a \
+           clangARCMigrate.a clangRewrite.a clangEdit.a \
+           clangAnalysis.a clangAST.a clangLex.a clangBasic.a
+
+include $(CLANG_LEVEL)/unittests/Makefile
diff --git a/clang/unittests/Lex/LexerTest.cpp b/clang/unittests/Lex/LexerTest.cpp
new file mode 100644
index 0000000..e43ad86
--- /dev/null
+++ b/clang/unittests/Lex/LexerTest.cpp
@@ -0,0 +1,177 @@
+//===- unittests/Basic/LexerTest.cpp ------ Lexer tests -------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/TargetOptions.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/ModuleLoader.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/Config/config.h"
+
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace clang;
+
+namespace {
+
+// The test fixture.
+class LexerTest : public ::testing::Test {
+protected:
+  LexerTest()
+    : FileMgr(FileMgrOpts),
+      DiagID(new DiagnosticIDs()),
+      Diags(DiagID, new IgnoringDiagConsumer()),
+      SourceMgr(Diags, FileMgr) {
+    TargetOpts.Triple = "x86_64-apple-darwin11.1.0";
+    Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
+  }
+
+  FileSystemOptions FileMgrOpts;
+  FileManager FileMgr;
+  IntrusiveRefCntPtr<DiagnosticIDs> DiagID;
+  DiagnosticsEngine Diags;
+  SourceManager SourceMgr;
+  LangOptions LangOpts;
+  TargetOptions TargetOpts;
+  IntrusiveRefCntPtr<TargetInfo> Target;
+};
+
+class VoidModuleLoader : public ModuleLoader {
+  virtual Module *loadModule(SourceLocation ImportLoc, ModuleIdPath Path,
+                             Module::NameVisibilityKind Visibility,
+                             bool IsInclusionDirective) {
+    return 0;
+  }
+};
+
+TEST_F(LexerTest, LexAPI) {
+  const char *source =
+    "#define M(x) [x]\n"
+    "#define N(x) x\n"
+    "#define INN(x) x\n"
+    "#define NOF1 INN(val)\n"
+    "#define NOF2 val\n"
+    "M(foo) N([bar])\n"
+    "N(INN(val)) N(NOF1) N(NOF2) N(val)";
+
+  MemoryBuffer *buf = MemoryBuffer::getMemBuffer(source);
+  (void)SourceMgr.createMainFileIDForMemBuffer(buf);
+
+  VoidModuleLoader ModLoader;
+  HeaderSearch HeaderInfo(FileMgr, Diags, LangOpts, Target.getPtr());
+  Preprocessor PP(Diags, LangOpts,
+                  Target.getPtr(),
+                  SourceMgr, HeaderInfo, ModLoader,
+                  /*IILookup =*/ 0,
+                  /*OwnsHeaderSearch =*/false,
+                  /*DelayInitialization =*/ false);
+  PP.EnterMainSourceFile();
+
+  std::vector<Token> toks;
+  while (1) {
+    Token tok;
+    PP.Lex(tok);
+    if (tok.is(tok::eof))
+      break;
+    toks.push_back(tok);
+  }
+
+  // Make sure we got the tokens that we expected.
+  ASSERT_EQ(10U, toks.size());
+  ASSERT_EQ(tok::l_square, toks[0].getKind());
+  ASSERT_EQ(tok::identifier, toks[1].getKind());
+  ASSERT_EQ(tok::r_square, toks[2].getKind());
+  ASSERT_EQ(tok::l_square, toks[3].getKind());
+  ASSERT_EQ(tok::identifier, toks[4].getKind());
+  ASSERT_EQ(tok::r_square, toks[5].getKind());
+  ASSERT_EQ(tok::identifier, toks[6].getKind());
+  ASSERT_EQ(tok::identifier, toks[7].getKind());
+  ASSERT_EQ(tok::identifier, toks[8].getKind());
+  ASSERT_EQ(tok::identifier, toks[9].getKind());
+  
+  SourceLocation lsqrLoc = toks[0].getLocation();
+  SourceLocation idLoc = toks[1].getLocation();
+  SourceLocation rsqrLoc = toks[2].getLocation();
+  std::pair<SourceLocation,SourceLocation>
+    macroPair = SourceMgr.getExpansionRange(lsqrLoc);
+  SourceRange macroRange = SourceRange(macroPair.first, macroPair.second);
+
+  SourceLocation Loc;
+  EXPECT_TRUE(Lexer::isAtStartOfMacroExpansion(lsqrLoc, SourceMgr, LangOpts, &Loc));
+  EXPECT_EQ(Loc, macroRange.getBegin());
+  EXPECT_FALSE(Lexer::isAtStartOfMacroExpansion(idLoc, SourceMgr, LangOpts));
+  EXPECT_FALSE(Lexer::isAtEndOfMacroExpansion(idLoc, SourceMgr, LangOpts));
+  EXPECT_TRUE(Lexer::isAtEndOfMacroExpansion(rsqrLoc, SourceMgr, LangOpts, &Loc));
+  EXPECT_EQ(Loc, macroRange.getEnd());
+
+  CharSourceRange range = Lexer::makeFileCharRange(
+           CharSourceRange::getTokenRange(lsqrLoc, idLoc), SourceMgr, LangOpts);
+  EXPECT_TRUE(range.isInvalid());
+  range = Lexer::makeFileCharRange(CharSourceRange::getTokenRange(idLoc, rsqrLoc),
+                                   SourceMgr, LangOpts);
+  EXPECT_TRUE(range.isInvalid());
+  range = Lexer::makeFileCharRange(CharSourceRange::getTokenRange(lsqrLoc, rsqrLoc),
+                                   SourceMgr, LangOpts);
+  EXPECT_TRUE(!range.isTokenRange());
+  EXPECT_EQ(range.getAsRange(),
+            SourceRange(macroRange.getBegin(),
+                        macroRange.getEnd().getLocWithOffset(1)));
+
+  StringRef text = Lexer::getSourceText(
+                               CharSourceRange::getTokenRange(lsqrLoc, rsqrLoc),
+                               SourceMgr, LangOpts);
+  EXPECT_EQ(text, "M(foo)");
+
+  SourceLocation macroLsqrLoc = toks[3].getLocation();
+  SourceLocation macroIdLoc = toks[4].getLocation();
+  SourceLocation macroRsqrLoc = toks[5].getLocation();
+  SourceLocation fileLsqrLoc = SourceMgr.getSpellingLoc(macroLsqrLoc);
+  SourceLocation fileIdLoc = SourceMgr.getSpellingLoc(macroIdLoc);
+  SourceLocation fileRsqrLoc = SourceMgr.getSpellingLoc(macroRsqrLoc);
+
+  range = Lexer::makeFileCharRange(
+      CharSourceRange::getTokenRange(macroLsqrLoc, macroIdLoc),
+      SourceMgr, LangOpts);
+  EXPECT_EQ(SourceRange(fileLsqrLoc, fileIdLoc.getLocWithOffset(3)),
+            range.getAsRange());
+
+  range = Lexer::makeFileCharRange(CharSourceRange::getTokenRange(macroIdLoc, macroRsqrLoc),
+                                   SourceMgr, LangOpts);
+  EXPECT_EQ(SourceRange(fileIdLoc, fileRsqrLoc.getLocWithOffset(1)),
+            range.getAsRange());
+
+  macroPair = SourceMgr.getExpansionRange(macroLsqrLoc);
+  range = Lexer::makeFileCharRange(
+                     CharSourceRange::getTokenRange(macroLsqrLoc, macroRsqrLoc),
+                     SourceMgr, LangOpts);
+  EXPECT_EQ(SourceRange(macroPair.first, macroPair.second.getLocWithOffset(1)),
+            range.getAsRange());
+
+  text = Lexer::getSourceText(
+          CharSourceRange::getTokenRange(SourceRange(macroLsqrLoc, macroIdLoc)),
+          SourceMgr, LangOpts);
+  EXPECT_EQ(text, "[bar");
+
+
+  SourceLocation idLoc1 = toks[6].getLocation();
+  SourceLocation idLoc2 = toks[7].getLocation();
+  SourceLocation idLoc3 = toks[8].getLocation();
+  SourceLocation idLoc4 = toks[9].getLocation();
+  EXPECT_EQ("INN", Lexer::getImmediateMacroName(idLoc1, SourceMgr, LangOpts));
+  EXPECT_EQ("INN", Lexer::getImmediateMacroName(idLoc2, SourceMgr, LangOpts));
+  EXPECT_EQ("NOF2", Lexer::getImmediateMacroName(idLoc3, SourceMgr, LangOpts));
+  EXPECT_EQ("N", Lexer::getImmediateMacroName(idLoc4, SourceMgr, LangOpts));
+}
+
+} // anonymous namespace
diff --git a/clang/unittests/Lex/Makefile b/clang/unittests/Lex/Makefile
new file mode 100644
index 0000000..bb9c6bc
--- /dev/null
+++ b/clang/unittests/Lex/Makefile
@@ -0,0 +1,15 @@
+##===- unittests/Lex/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 = ../..
+TESTNAME = Lex
+LINK_COMPONENTS := support mc
+USEDLIBS = clangLex.a clangBasic.a
+
+include $(CLANG_LEVEL)/unittests/Makefile
diff --git a/clang/unittests/Lex/PreprocessingRecordTest.cpp b/clang/unittests/Lex/PreprocessingRecordTest.cpp
new file mode 100644
index 0000000..5b5d933
--- /dev/null
+++ b/clang/unittests/Lex/PreprocessingRecordTest.cpp
@@ -0,0 +1,139 @@
+//===- unittests/Lex/PreprocessingRecordTest.cpp - PreprocessingRecord tests =//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/TargetOptions.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Lex/ModuleLoader.h"
+#include "clang/Lex/HeaderSearch.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/PreprocessingRecord.h"
+#include "llvm/Config/config.h"
+
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace clang;
+
+namespace {
+
+// The test fixture.
+class PreprocessingRecordTest : public ::testing::Test {
+protected:
+  PreprocessingRecordTest()
+    : FileMgr(FileMgrOpts),
+      DiagID(new DiagnosticIDs()),
+      Diags(DiagID, new IgnoringDiagConsumer()),
+      SourceMgr(Diags, FileMgr) {
+    TargetOpts.Triple = "x86_64-apple-darwin11.1.0";
+    Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
+  }
+
+  FileSystemOptions FileMgrOpts;
+  FileManager FileMgr;
+  IntrusiveRefCntPtr<DiagnosticIDs> DiagID;
+  DiagnosticsEngine Diags;
+  SourceManager SourceMgr;
+  LangOptions LangOpts;
+  TargetOptions TargetOpts;
+  IntrusiveRefCntPtr<TargetInfo> Target;
+};
+
+class VoidModuleLoader : public ModuleLoader {
+  virtual Module *loadModule(SourceLocation ImportLoc, ModuleIdPath Path,
+                             Module::NameVisibilityKind Visibility,
+                             bool IsInclusionDirective) {
+    return 0;
+  }
+};
+
+TEST_F(PreprocessingRecordTest, PPRecAPI) {
+  const char *source =
+      "0 1\n"
+      "#if 1\n"
+      "2\n"
+      "#ifndef BB\n"
+      "3 4\n"
+      "#else\n"
+      "#endif\n"
+      "5\n"
+      "#endif\n"
+      "6\n"
+      "#if 1\n"
+      "7\n"
+      "#if 1\n"
+      "#endif\n"
+      "8\n"
+      "#endif\n"
+      "9\n";
+
+  MemoryBuffer *buf = MemoryBuffer::getMemBuffer(source);
+  SourceMgr.createMainFileIDForMemBuffer(buf);
+
+  VoidModuleLoader ModLoader;
+  HeaderSearch HeaderInfo(FileMgr, Diags, LangOpts, Target.getPtr());
+  Preprocessor PP(Diags, LangOpts,
+                  Target.getPtr(),
+                  SourceMgr, HeaderInfo, ModLoader,
+                  /*IILookup =*/ 0,
+                  /*OwnsHeaderSearch =*/false,
+                  /*DelayInitialization =*/ false);
+  PP.createPreprocessingRecord(true);
+  PP.EnterMainSourceFile();
+
+  std::vector<Token> toks;
+  while (1) {
+    Token tok;
+    PP.Lex(tok);
+    if (tok.is(tok::eof))
+      break;
+    toks.push_back(tok);
+  }
+
+  // Make sure we got the tokens that we expected.
+  ASSERT_EQ(10U, toks.size());
+  
+  PreprocessingRecord &PPRec = *PP.getPreprocessingRecord();
+  EXPECT_FALSE(PPRec.rangeIntersectsConditionalDirective(
+                    SourceRange(toks[0].getLocation(), toks[1].getLocation())));
+  EXPECT_TRUE(PPRec.rangeIntersectsConditionalDirective(
+                    SourceRange(toks[0].getLocation(), toks[2].getLocation())));
+  EXPECT_FALSE(PPRec.rangeIntersectsConditionalDirective(
+                    SourceRange(toks[3].getLocation(), toks[4].getLocation())));
+  EXPECT_TRUE(PPRec.rangeIntersectsConditionalDirective(
+                    SourceRange(toks[1].getLocation(), toks[5].getLocation())));
+  EXPECT_TRUE(PPRec.rangeIntersectsConditionalDirective(
+                    SourceRange(toks[2].getLocation(), toks[6].getLocation())));
+  EXPECT_FALSE(PPRec.rangeIntersectsConditionalDirective(
+                    SourceRange(toks[2].getLocation(), toks[5].getLocation())));
+  EXPECT_FALSE(PPRec.rangeIntersectsConditionalDirective(
+                    SourceRange(toks[0].getLocation(), toks[6].getLocation())));
+  EXPECT_TRUE(PPRec.rangeIntersectsConditionalDirective(
+                    SourceRange(toks[2].getLocation(), toks[8].getLocation())));
+  EXPECT_FALSE(PPRec.rangeIntersectsConditionalDirective(
+                    SourceRange(toks[0].getLocation(), toks[9].getLocation())));
+
+  EXPECT_TRUE(PPRec.areInDifferentConditionalDirectiveRegion(
+                    toks[0].getLocation(), toks[2].getLocation()));
+  EXPECT_FALSE(PPRec.areInDifferentConditionalDirectiveRegion(
+                    toks[3].getLocation(), toks[4].getLocation()));
+  EXPECT_TRUE(PPRec.areInDifferentConditionalDirectiveRegion(
+                    toks[1].getLocation(), toks[5].getLocation()));
+  EXPECT_TRUE(PPRec.areInDifferentConditionalDirectiveRegion(
+                    toks[2].getLocation(), toks[0].getLocation()));
+  EXPECT_FALSE(PPRec.areInDifferentConditionalDirectiveRegion(
+                    toks[4].getLocation(), toks[3].getLocation()));
+  EXPECT_TRUE(PPRec.areInDifferentConditionalDirectiveRegion(
+                    toks[5].getLocation(), toks[1].getLocation()));
+}
+
+} // anonymous namespace
diff --git a/clang/unittests/Makefile b/clang/unittests/Makefile
new file mode 100644
index 0000000..05449d8
--- /dev/null
+++ b/clang/unittests/Makefile
@@ -0,0 +1,28 @@
+##===- unittests/Makefile ----------------------------------*- Makefile -*-===##
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+# If CLANG_LEVEL is not set, then we are the top-level Makefile. Otherwise, we
+# are being included from a subdirectory makefile.
+
+ifndef CLANG_LEVEL
+
+IS_UNITTEST_LEVEL := 1
+CLANG_LEVEL := ..
+PARALLEL_DIRS = Basic Frontend Lex Tooling
+
+endif  # CLANG_LEVEL
+
+include $(CLANG_LEVEL)/Makefile
+
+ifndef IS_UNITTEST_LEVEL
+
+MAKEFILE_UNITTEST_NO_INCLUDE_COMMON := 1
+include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
+
+endif  # IS_UNITTEST_LEVEL
diff --git a/clang/unittests/Tooling/CompilationDatabaseTest.cpp b/clang/unittests/Tooling/CompilationDatabaseTest.cpp
new file mode 100644
index 0000000..68d2896
--- /dev/null
+++ b/clang/unittests/Tooling/CompilationDatabaseTest.cpp
@@ -0,0 +1,292 @@
+//===- unittest/Tooling/CompilationDatabaseTest.cpp -----------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclGroup.h"
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/Tooling/CompilationDatabase.h"
+#include "clang/Tooling/Tooling.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace tooling {
+
+static CompileCommand findCompileArgsInJsonDatabase(StringRef FileName,
+                                                    StringRef JSONDatabase,
+                                                    std::string &ErrorMessage) {
+  llvm::OwningPtr<CompilationDatabase> Database(
+      JSONCompilationDatabase::loadFromBuffer(JSONDatabase, ErrorMessage));
+  if (!Database)
+    return CompileCommand();
+  std::vector<CompileCommand> Commands = Database->getCompileCommands(FileName);
+  EXPECT_LE(Commands.size(), 1u);
+  if (Commands.empty())
+    return CompileCommand();
+  return Commands[0];
+}
+
+TEST(findCompileArgsInJsonDatabase, FindsNothingIfEmpty) {
+  std::string ErrorMessage;
+  CompileCommand NotFound = findCompileArgsInJsonDatabase(
+    "a-file.cpp", "", ErrorMessage);
+  EXPECT_TRUE(NotFound.CommandLine.empty()) << ErrorMessage;
+  EXPECT_TRUE(NotFound.Directory.empty()) << ErrorMessage;
+}
+
+TEST(findCompileArgsInJsonDatabase, ReadsSingleEntry) {
+  StringRef Directory("/some/directory");
+  StringRef FileName("/path/to/a-file.cpp");
+  StringRef Command("/path/to/compiler and some arguments");
+  std::string ErrorMessage;
+  CompileCommand FoundCommand = findCompileArgsInJsonDatabase(
+    FileName,
+    ("[{\"directory\":\"" + Directory + "\"," +
+       "\"command\":\"" + Command + "\","
+       "\"file\":\"" + FileName + "\"}]").str(),
+    ErrorMessage);
+  EXPECT_EQ(Directory, FoundCommand.Directory) << ErrorMessage;
+  ASSERT_EQ(4u, FoundCommand.CommandLine.size()) << ErrorMessage;
+  EXPECT_EQ("/path/to/compiler", FoundCommand.CommandLine[0]) << ErrorMessage;
+  EXPECT_EQ("and", FoundCommand.CommandLine[1]) << ErrorMessage;
+  EXPECT_EQ("some", FoundCommand.CommandLine[2]) << ErrorMessage;
+  EXPECT_EQ("arguments", FoundCommand.CommandLine[3]) << ErrorMessage;
+
+  CompileCommand NotFound = findCompileArgsInJsonDatabase(
+    "a-file.cpp",
+    ("[{\"directory\":\"" + Directory + "\"," +
+       "\"command\":\"" + Command + "\","
+       "\"file\":\"" + FileName + "\"}]").str(),
+    ErrorMessage);
+  EXPECT_TRUE(NotFound.Directory.empty()) << ErrorMessage;
+  EXPECT_TRUE(NotFound.CommandLine.empty()) << ErrorMessage;
+}
+
+TEST(findCompileArgsInJsonDatabase, ReadsCompileCommandLinesWithSpaces) {
+  StringRef Directory("/some/directory");
+  StringRef FileName("/path/to/a-file.cpp");
+  StringRef Command("\\\"/path to compiler\\\" \\\"and an argument\\\"");
+  std::string ErrorMessage;
+  CompileCommand FoundCommand = findCompileArgsInJsonDatabase(
+    FileName,
+    ("[{\"directory\":\"" + Directory + "\"," +
+       "\"command\":\"" + Command + "\","
+       "\"file\":\"" + FileName + "\"}]").str(),
+    ErrorMessage);
+  ASSERT_EQ(2u, FoundCommand.CommandLine.size());
+  EXPECT_EQ("/path to compiler", FoundCommand.CommandLine[0]) << ErrorMessage;
+  EXPECT_EQ("and an argument", FoundCommand.CommandLine[1]) << ErrorMessage;
+}
+
+TEST(findCompileArgsInJsonDatabase, ReadsDirectoryWithSpaces) {
+  StringRef Directory("/some directory / with spaces");
+  StringRef FileName("/path/to/a-file.cpp");
+  StringRef Command("a command");
+  std::string ErrorMessage;
+  CompileCommand FoundCommand = findCompileArgsInJsonDatabase(
+    FileName,
+    ("[{\"directory\":\"" + Directory + "\"," +
+       "\"command\":\"" + Command + "\","
+       "\"file\":\"" + FileName + "\"}]").str(),
+    ErrorMessage);
+  EXPECT_EQ(Directory, FoundCommand.Directory) << ErrorMessage;
+}
+
+TEST(findCompileArgsInJsonDatabase, FindsEntry) {
+  StringRef Directory("directory");
+  StringRef FileName("file");
+  StringRef Command("command");
+  std::string JsonDatabase = "[";
+  for (int I = 0; I < 10; ++I) {
+    if (I > 0) JsonDatabase += ",";
+    JsonDatabase +=
+      ("{\"directory\":\"" + Directory + Twine(I) + "\"," +
+        "\"command\":\"" + Command + Twine(I) + "\","
+        "\"file\":\"" + FileName + Twine(I) + "\"}").str();
+  }
+  JsonDatabase += "]";
+  std::string ErrorMessage;
+  CompileCommand FoundCommand = findCompileArgsInJsonDatabase(
+    "file4", JsonDatabase, ErrorMessage);
+  EXPECT_EQ("directory4", FoundCommand.Directory) << ErrorMessage;
+  ASSERT_EQ(1u, FoundCommand.CommandLine.size()) << ErrorMessage;
+  EXPECT_EQ("command4", FoundCommand.CommandLine[0]) << ErrorMessage;
+}
+
+static std::vector<std::string> unescapeJsonCommandLine(StringRef Command) {
+  std::string JsonDatabase =
+    ("[{\"directory\":\"\", \"file\":\"test\", \"command\": \"" +
+     Command + "\"}]").str();
+  std::string ErrorMessage;
+  CompileCommand FoundCommand = findCompileArgsInJsonDatabase(
+    "test", JsonDatabase, ErrorMessage);
+  EXPECT_TRUE(ErrorMessage.empty()) << ErrorMessage;
+  return FoundCommand.CommandLine;
+}
+
+TEST(unescapeJsonCommandLine, ReturnsEmptyArrayOnEmptyString) {
+  std::vector<std::string> Result = unescapeJsonCommandLine("");
+  EXPECT_TRUE(Result.empty());
+}
+
+TEST(unescapeJsonCommandLine, SplitsOnSpaces) {
+  std::vector<std::string> Result = unescapeJsonCommandLine("a b c");
+  ASSERT_EQ(3ul, Result.size());
+  EXPECT_EQ("a", Result[0]);
+  EXPECT_EQ("b", Result[1]);
+  EXPECT_EQ("c", Result[2]);
+}
+
+TEST(unescapeJsonCommandLine, MungesMultipleSpaces) {
+  std::vector<std::string> Result = unescapeJsonCommandLine("   a   b   ");
+  ASSERT_EQ(2ul, Result.size());
+  EXPECT_EQ("a", Result[0]);
+  EXPECT_EQ("b", Result[1]);
+}
+
+TEST(unescapeJsonCommandLine, UnescapesBackslashCharacters) {
+  std::vector<std::string> Backslash = unescapeJsonCommandLine("a\\\\\\\\");
+  ASSERT_EQ(1ul, Backslash.size());
+  EXPECT_EQ("a\\", Backslash[0]);
+  std::vector<std::string> Quote = unescapeJsonCommandLine("a\\\\\\\"");
+  ASSERT_EQ(1ul, Quote.size());
+  EXPECT_EQ("a\"", Quote[0]);
+}
+
+TEST(unescapeJsonCommandLine, DoesNotMungeSpacesBetweenQuotes) {
+  std::vector<std::string> Result = unescapeJsonCommandLine("\\\"  a  b  \\\"");
+  ASSERT_EQ(1ul, Result.size());
+  EXPECT_EQ("  a  b  ", Result[0]);
+}
+
+TEST(unescapeJsonCommandLine, AllowsMultipleQuotedArguments) {
+  std::vector<std::string> Result = unescapeJsonCommandLine(
+      "  \\\" a \\\"  \\\" b \\\"  ");
+  ASSERT_EQ(2ul, Result.size());
+  EXPECT_EQ(" a ", Result[0]);
+  EXPECT_EQ(" b ", Result[1]);
+}
+
+TEST(unescapeJsonCommandLine, AllowsEmptyArgumentsInQuotes) {
+  std::vector<std::string> Result = unescapeJsonCommandLine(
+      "\\\"\\\"\\\"\\\"");
+  ASSERT_EQ(1ul, Result.size());
+  EXPECT_TRUE(Result[0].empty()) << Result[0];
+}
+
+TEST(unescapeJsonCommandLine, ParsesEscapedQuotesInQuotedStrings) {
+  std::vector<std::string> Result = unescapeJsonCommandLine(
+      "\\\"\\\\\\\"\\\"");
+  ASSERT_EQ(1ul, Result.size());
+  EXPECT_EQ("\"", Result[0]);
+}
+
+TEST(unescapeJsonCommandLine, ParsesMultipleArgumentsWithEscapedCharacters) {
+  std::vector<std::string> Result = unescapeJsonCommandLine(
+      "  \\\\\\\"  \\\"a \\\\\\\" b \\\"     \\\"and\\\\\\\\c\\\"   \\\\\\\"");
+  ASSERT_EQ(4ul, Result.size());
+  EXPECT_EQ("\"", Result[0]);
+  EXPECT_EQ("a \" b ", Result[1]);
+  EXPECT_EQ("and\\c", Result[2]);
+  EXPECT_EQ("\"", Result[3]);
+}
+
+TEST(unescapeJsonCommandLine, ParsesStringsWithoutSpacesIntoSingleArgument) {
+  std::vector<std::string> QuotedNoSpaces = unescapeJsonCommandLine(
+      "\\\"a\\\"\\\"b\\\"");
+  ASSERT_EQ(1ul, QuotedNoSpaces.size());
+  EXPECT_EQ("ab", QuotedNoSpaces[0]);
+
+  std::vector<std::string> MixedNoSpaces = unescapeJsonCommandLine(
+      "\\\"a\\\"bcd\\\"ef\\\"\\\"\\\"\\\"g\\\"");
+  ASSERT_EQ(1ul, MixedNoSpaces.size());
+  EXPECT_EQ("abcdefg", MixedNoSpaces[0]);
+}
+
+TEST(unescapeJsonCommandLine, ParsesQuotedStringWithoutClosingQuote) {
+  std::vector<std::string> Unclosed = unescapeJsonCommandLine("\\\"abc");
+  ASSERT_EQ(1ul, Unclosed.size());
+  EXPECT_EQ("abc", Unclosed[0]);
+
+  std::vector<std::string> Empty = unescapeJsonCommandLine("\\\"");
+  ASSERT_EQ(1ul, Empty.size());
+  EXPECT_EQ("", Empty[0]);
+}
+
+TEST(FixedCompilationDatabase, ReturnsFixedCommandLine) {
+  std::vector<std::string> CommandLine;
+  CommandLine.push_back("one");
+  CommandLine.push_back("two");
+  FixedCompilationDatabase Database(".", CommandLine);
+  std::vector<CompileCommand> Result =
+    Database.getCompileCommands("source");
+  ASSERT_EQ(1ul, Result.size());
+  std::vector<std::string> ExpectedCommandLine(1, "clang-tool");
+  ExpectedCommandLine.insert(ExpectedCommandLine.end(),
+                             CommandLine.begin(), CommandLine.end());
+  ExpectedCommandLine.push_back("source");
+  EXPECT_EQ(".", Result[0].Directory);
+  EXPECT_EQ(ExpectedCommandLine, Result[0].CommandLine);
+}
+
+TEST(ParseFixedCompilationDatabase, ReturnsNullOnEmptyArgumentList) {
+  int Argc = 0;
+  llvm::OwningPtr<FixedCompilationDatabase> Database(
+      FixedCompilationDatabase::loadFromCommandLine(Argc, NULL));
+  EXPECT_FALSE(Database);
+  EXPECT_EQ(0, Argc);
+}
+
+TEST(ParseFixedCompilationDatabase, ReturnsNullWithoutDoubleDash) {
+  int Argc = 2;
+  const char *Argv[] = { "1", "2" };
+  llvm::OwningPtr<FixedCompilationDatabase> Database(
+      FixedCompilationDatabase::loadFromCommandLine(Argc, Argv));
+  EXPECT_FALSE(Database);
+  EXPECT_EQ(2, Argc);
+}
+
+TEST(ParseFixedCompilationDatabase, ReturnsArgumentsAfterDoubleDash) {
+  int Argc = 5;
+  const char *Argv[] = { "1", "2", "--\0no-constant-folding", "3", "4" };
+  llvm::OwningPtr<FixedCompilationDatabase> Database(
+      FixedCompilationDatabase::loadFromCommandLine(Argc, Argv));
+  ASSERT_TRUE(Database);
+  std::vector<CompileCommand> Result =
+    Database->getCompileCommands("source");
+  ASSERT_EQ(1ul, Result.size());
+  ASSERT_EQ(".", Result[0].Directory);
+  std::vector<std::string> CommandLine;
+  CommandLine.push_back("clang-tool");
+  CommandLine.push_back("3");
+  CommandLine.push_back("4");
+  CommandLine.push_back("source");
+  ASSERT_EQ(CommandLine, Result[0].CommandLine);
+  EXPECT_EQ(2, Argc);
+}
+
+TEST(ParseFixedCompilationDatabase, ReturnsEmptyCommandLine) {
+  int Argc = 3;
+  const char *Argv[] = { "1", "2", "--\0no-constant-folding" };
+  llvm::OwningPtr<FixedCompilationDatabase> Database(
+      FixedCompilationDatabase::loadFromCommandLine(Argc, Argv));
+  ASSERT_TRUE(Database);
+  std::vector<CompileCommand> Result =
+    Database->getCompileCommands("source");
+  ASSERT_EQ(1ul, Result.size());
+  ASSERT_EQ(".", Result[0].Directory);
+  std::vector<std::string> CommandLine;
+  CommandLine.push_back("clang-tool");
+  CommandLine.push_back("source");
+  ASSERT_EQ(CommandLine, Result[0].CommandLine);
+  EXPECT_EQ(2, Argc);
+}
+
+} // end namespace tooling
+} // end namespace clang
diff --git a/clang/unittests/Tooling/Makefile b/clang/unittests/Tooling/Makefile
new file mode 100644
index 0000000..0829da5
--- /dev/null
+++ b/clang/unittests/Tooling/Makefile
@@ -0,0 +1,17 @@
+##===- unittests/Tooling/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 = ../..
+TESTNAME = Tooling
+LINK_COMPONENTS := support mc
+USEDLIBS = clangTooling.a clangFrontend.a clangSerialization.a clangDriver.a \
+           clangParse.a clangSema.a clangAnalysis.a clangEdit.a clangAST.a \
+           clangLex.a clangBasic.a
+
+include $(CLANG_LEVEL)/unittests/Makefile
diff --git a/clang/unittests/Tooling/ToolingTest.cpp b/clang/unittests/Tooling/ToolingTest.cpp
new file mode 100644
index 0000000..c7b2210
--- /dev/null
+++ b/clang/unittests/Tooling/ToolingTest.cpp
@@ -0,0 +1,113 @@
+//===- unittest/Tooling/ToolingTest.cpp - Tooling unit tests --------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclGroup.h"
+#include "clang/Frontend/FrontendAction.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Tooling/CompilationDatabase.h"
+#include "clang/Tooling/Tooling.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace tooling {
+
+namespace {
+/// Takes an ast consumer and returns it from CreateASTConsumer. This only
+/// works with single translation unit compilations.
+class TestAction : public clang::ASTFrontendAction {
+ public:
+  /// Takes ownership of TestConsumer.
+  explicit TestAction(clang::ASTConsumer *TestConsumer)
+      : TestConsumer(TestConsumer) {}
+
+ protected:
+  virtual clang::ASTConsumer* CreateASTConsumer(
+      clang::CompilerInstance& compiler, StringRef dummy) {
+    /// TestConsumer will be deleted by the framework calling us.
+    return TestConsumer;
+  }
+
+ private:
+  clang::ASTConsumer * const TestConsumer;
+};
+
+class FindTopLevelDeclConsumer : public clang::ASTConsumer {
+ public:
+  explicit FindTopLevelDeclConsumer(bool *FoundTopLevelDecl)
+      : FoundTopLevelDecl(FoundTopLevelDecl) {}
+  virtual bool HandleTopLevelDecl(clang::DeclGroupRef DeclGroup) {
+    *FoundTopLevelDecl = true;
+    return true;
+  }
+ private:
+  bool * const FoundTopLevelDecl;
+};
+} // end namespace
+
+TEST(runToolOnCode, FindsTopLevelDeclOnEmptyCode) {
+  bool FoundTopLevelDecl = false;
+  EXPECT_TRUE(runToolOnCode(
+      new TestAction(new FindTopLevelDeclConsumer(&FoundTopLevelDecl)), ""));
+  EXPECT_TRUE(FoundTopLevelDecl);
+}
+
+namespace {
+class FindClassDeclXConsumer : public clang::ASTConsumer {
+ public:
+  FindClassDeclXConsumer(bool *FoundClassDeclX)
+      : FoundClassDeclX(FoundClassDeclX) {}
+  virtual bool HandleTopLevelDecl(clang::DeclGroupRef GroupRef) {
+    if (CXXRecordDecl* Record = dyn_cast<clang::CXXRecordDecl>(
+            *GroupRef.begin())) {
+      if (Record->getName() == "X") {
+        *FoundClassDeclX = true;
+      }
+    }
+    return true;
+  }
+ private:
+  bool *FoundClassDeclX;
+};
+} // end namespace
+
+TEST(runToolOnCode, FindsClassDecl) {
+  bool FoundClassDeclX = false;
+  EXPECT_TRUE(runToolOnCode(new TestAction(
+      new FindClassDeclXConsumer(&FoundClassDeclX)), "class X;"));
+  EXPECT_TRUE(FoundClassDeclX);
+
+  FoundClassDeclX = false;
+  EXPECT_TRUE(runToolOnCode(new TestAction(
+      new FindClassDeclXConsumer(&FoundClassDeclX)), "class Y;"));
+  EXPECT_FALSE(FoundClassDeclX);
+}
+
+TEST(newFrontendActionFactory, CreatesFrontendActionFactoryFromType) {
+  llvm::OwningPtr<FrontendActionFactory> Factory(
+    newFrontendActionFactory<SyntaxOnlyAction>());
+  llvm::OwningPtr<FrontendAction> Action(Factory->create());
+  EXPECT_TRUE(Action.get() != NULL);
+}
+
+struct IndependentFrontendActionCreator {
+  FrontendAction *newFrontendAction() { return new SyntaxOnlyAction; }
+};
+
+TEST(newFrontendActionFactory, CreatesFrontendActionFactoryFromFactoryType) {
+  IndependentFrontendActionCreator Creator;
+  llvm::OwningPtr<FrontendActionFactory> Factory(
+    newFrontendActionFactory(&Creator));
+  llvm::OwningPtr<FrontendAction> Action(Factory->create());
+  EXPECT_TRUE(Action.get() != NULL);
+}
+
+} // end namespace tooling
+} // end namespace clang
-- 
cgit v1.2.3