summaryrefslogtreecommitdiffstats
path: root/clang/unittests/Basic
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2012-03-27 18:47:48 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2012-03-27 18:47:48 +0000
commita956450eb755a26219b4f20ce7fe9c7f0f906640 (patch)
tree2e58d7f37b8a63cf2dfb96b8d057fe140fa9b677 /clang/unittests/Basic
parent5ed21c3154fcda3db8d0f44d1cbc72d35391cf21 (diff)
downloadbcm5719-llvm-a956450eb755a26219b4f20ce7fe9c7f0f906640.tar.gz
bcm5719-llvm-a956450eb755a26219b4f20ce7fe9c7f0f906640.zip
[preprocessor] Handle correctly inclusion directives that have macro expansions, e.g
"#include MACRO(STUFF)". -As an inclusion position for the included file, use the file location of the file where it was included but *after* the macro expansions. We want the macro expansions to be considered as before-in-translation-unit for everything in the included file. -In the preprocessing record take into account that only inclusion directives can be encountered as "out-of-order" (by comparing the start of the range which for inclusions is the hash location) and use binary search if there is an extreme number of macro expansions in the include directive. Fixes rdar://11111779 llvm-svn: 153527
Diffstat (limited to 'clang/unittests/Basic')
-rw-r--r--clang/unittests/Basic/SourceManagerTest.cpp115
1 files changed, 115 insertions, 0 deletions
diff --git a/clang/unittests/Basic/SourceManagerTest.cpp b/clang/unittests/Basic/SourceManagerTest.cpp
index 65d57b67b58..429b58d7ea4 100644
--- a/clang/unittests/Basic/SourceManagerTest.cpp
+++ b/clang/unittests/Basic/SourceManagerTest.cpp
@@ -176,6 +176,121 @@ TEST_F(SourceManagerTest, getMacroArgExpandedLocation) {
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
OpenPOWER on IntegriCloud