Fix bugs in SourceManager::computeMacroArgsCache() and add a unit test for it.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147057 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/unittests/Basic/SourceManagerTest.cpp b/unittests/Basic/SourceManagerTest.cpp
index caab441..4122f0d 100644
--- a/unittests/Basic/SourceManagerTest.cpp
+++ b/unittests/Basic/SourceManagerTest.cpp
@@ -16,6 +16,7 @@
 #include "clang/Lex/ModuleLoader.h"
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/Preprocessor.h"
+#include "llvm/Config/config.h"
 
 #include "gtest/gtest.h"
 
@@ -105,4 +106,75 @@
   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);
+  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());
+}
+
+#endif
+
 } // anonymous namespace