blob: b5a6fd90d08fde59d73375d0bd545febc207f026 [file] [log] [blame]
Chandler Carruth320d9662012-12-04 09:45:34 +00001//===- unittests/Lex/LexerTest.cpp ------ Lexer tests ---------------------===//
Argyrios Kyrtzidisd1699112012-01-19 15:59:01 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Chandler Carruth320d9662012-12-04 09:45:34 +000010#include "clang/Lex/Lexer.h"
Argyrios Kyrtzidisd1699112012-01-19 15:59:01 +000011#include "clang/Basic/Diagnostic.h"
Douglas Gregoredf8e382012-10-23 22:38:58 +000012#include "clang/Basic/DiagnosticOptions.h"
Chandler Carruth320d9662012-12-04 09:45:34 +000013#include "clang/Basic/FileManager.h"
Argyrios Kyrtzidisd1699112012-01-19 15:59:01 +000014#include "clang/Basic/LangOptions.h"
Duncan P. N. Exon Smith030d7d62017-03-20 17:58:26 +000015#include "clang/Basic/MemoryBufferCache.h"
Chandler Carruthfa0b3bb2012-12-04 09:53:37 +000016#include "clang/Basic/SourceManager.h"
Argyrios Kyrtzidisd1699112012-01-19 15:59:01 +000017#include "clang/Basic/TargetInfo.h"
Chandler Carruth320d9662012-12-04 09:45:34 +000018#include "clang/Basic/TargetOptions.h"
Argyrios Kyrtzidisd1699112012-01-19 15:59:01 +000019#include "clang/Lex/HeaderSearch.h"
Douglas Gregor40ba1a02012-10-24 16:24:38 +000020#include "clang/Lex/HeaderSearchOptions.h"
Chandler Carruth320d9662012-12-04 09:45:34 +000021#include "clang/Lex/ModuleLoader.h"
Argyrios Kyrtzidisd1699112012-01-19 15:59:01 +000022#include "clang/Lex/Preprocessor.h"
Douglas Gregor1452ff12012-10-24 17:46:57 +000023#include "clang/Lex/PreprocessorOptions.h"
Argyrios Kyrtzidisd1699112012-01-19 15:59:01 +000024#include "gtest/gtest.h"
25
Argyrios Kyrtzidisd1699112012-01-19 15:59:01 +000026using namespace clang;
27
28namespace {
29
Argyrios Kyrtzidisd1699112012-01-19 15:59:01 +000030class VoidModuleLoader : public ModuleLoader {
John Thompson2d94bbb2014-04-23 19:04:32 +000031 ModuleLoadResult loadModule(SourceLocation ImportLoc,
32 ModuleIdPath Path,
33 Module::NameVisibilityKind Visibility,
34 bool IsInclusionDirective) override {
Douglas Gregor8c058932012-11-30 00:01:57 +000035 return ModuleLoadResult();
Argyrios Kyrtzidisd1699112012-01-19 15:59:01 +000036 }
NAKAMURA Takumie73d2a92013-01-12 02:16:29 +000037
John Thompson2d94bbb2014-04-23 19:04:32 +000038 void makeModuleVisible(Module *Mod,
39 Module::NameVisibilityKind Visibility,
Richard Smitha7e2cc62015-05-01 01:53:09 +000040 SourceLocation ImportLoc) override { }
John Thompson2255f2c2014-04-23 12:57:01 +000041
John Thompson2d94bbb2014-04-23 19:04:32 +000042 GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override
Craig Topper416fa342014-06-08 08:38:12 +000043 { return nullptr; }
John Thompson2d94bbb2014-04-23 19:04:32 +000044 bool lookupMissingImports(StringRef Name, SourceLocation TriggerLoc) override
Hans Wennborg4afe5042015-07-22 20:46:26 +000045 { return 0; }
Argyrios Kyrtzidisd1699112012-01-19 15:59:01 +000046};
47
Argyrios Kyrtzidis065d7202013-05-16 21:37:39 +000048// The test fixture.
49class LexerTest : public ::testing::Test {
50protected:
51 LexerTest()
52 : FileMgr(FileMgrOpts),
53 DiagID(new DiagnosticIDs()),
54 Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()),
55 SourceMgr(Diags, FileMgr),
56 TargetOpts(new TargetOptions)
57 {
58 TargetOpts->Triple = "x86_64-apple-darwin11.1.0";
Alp Toker80758082014-07-06 05:26:44 +000059 Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
Argyrios Kyrtzidisd1699112012-01-19 15:59:01 +000060 }
61
Vedant Kumar95a2a7f2016-05-19 23:44:02 +000062 std::vector<Token> Lex(StringRef Source) {
James Y Knightb214cbc2016-03-04 19:00:41 +000063 std::unique_ptr<llvm::MemoryBuffer> Buf =
64 llvm::MemoryBuffer::getMemBuffer(Source);
David Blaikie50a5f972014-08-29 07:59:55 +000065 SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf)));
Argyrios Kyrtzidis065d7202013-05-16 21:37:39 +000066
67 VoidModuleLoader ModLoader;
Duncan P. N. Exon Smith030d7d62017-03-20 17:58:26 +000068 MemoryBufferCache PCMCache;
David Blaikie9c28cb32017-01-06 01:04:46 +000069 HeaderSearch HeaderInfo(std::make_shared<HeaderSearchOptions>(), SourceMgr,
70 Diags, LangOpts, Target.get());
David Blaikiee3041682017-01-05 19:11:36 +000071 Preprocessor PP(std::make_shared<PreprocessorOptions>(), Diags, LangOpts,
Duncan P. N. Exon Smith030d7d62017-03-20 17:58:26 +000072 SourceMgr, PCMCache, HeaderInfo, ModLoader,
73 /*IILookup =*/nullptr,
Alp Toker96637802014-05-02 03:43:38 +000074 /*OwnsHeaderSearch =*/false);
Alp Toker1ae02f62014-05-02 03:43:30 +000075 PP.Initialize(*Target);
Argyrios Kyrtzidis065d7202013-05-16 21:37:39 +000076 PP.EnterMainSourceFile();
77
78 std::vector<Token> toks;
79 while (1) {
80 Token tok;
81 PP.Lex(tok);
82 if (tok.is(tok::eof))
83 break;
84 toks.push_back(tok);
85 }
86
Vedant Kumar95a2a7f2016-05-19 23:44:02 +000087 return toks;
88 }
89
90 std::vector<Token> CheckLex(StringRef Source,
91 ArrayRef<tok::TokenKind> ExpectedTokens) {
92 auto toks = Lex(Source);
Argyrios Kyrtzidis065d7202013-05-16 21:37:39 +000093 EXPECT_EQ(ExpectedTokens.size(), toks.size());
94 for (unsigned i = 0, e = ExpectedTokens.size(); i != e; ++i) {
95 EXPECT_EQ(ExpectedTokens[i], toks[i].getKind());
96 }
97
98 return toks;
99 }
100
101 std::string getSourceText(Token Begin, Token End) {
102 bool Invalid;
103 StringRef Str =
104 Lexer::getSourceText(CharSourceRange::getTokenRange(SourceRange(
105 Begin.getLocation(), End.getLocation())),
106 SourceMgr, LangOpts, &Invalid);
107 if (Invalid)
108 return "<INVALID>";
109 return Str;
110 }
111
112 FileSystemOptions FileMgrOpts;
113 FileManager FileMgr;
114 IntrusiveRefCntPtr<DiagnosticIDs> DiagID;
115 DiagnosticsEngine Diags;
116 SourceManager SourceMgr;
117 LangOptions LangOpts;
Alp Toker80758082014-07-06 05:26:44 +0000118 std::shared_ptr<TargetOptions> TargetOpts;
Argyrios Kyrtzidis065d7202013-05-16 21:37:39 +0000119 IntrusiveRefCntPtr<TargetInfo> Target;
120};
121
122TEST_F(LexerTest, GetSourceTextExpandsToMaximumInMacroArgument) {
123 std::vector<tok::TokenKind> ExpectedTokens;
124 ExpectedTokens.push_back(tok::identifier);
125 ExpectedTokens.push_back(tok::l_paren);
126 ExpectedTokens.push_back(tok::identifier);
127 ExpectedTokens.push_back(tok::r_paren);
128
129 std::vector<Token> toks = CheckLex("#define M(x) x\n"
130 "M(f(M(i)))",
131 ExpectedTokens);
132
133 EXPECT_EQ("M(i)", getSourceText(toks[2], toks[2]));
134}
135
136TEST_F(LexerTest, GetSourceTextExpandsToMaximumInMacroArgumentForEndOfMacro) {
137 std::vector<tok::TokenKind> ExpectedTokens;
138 ExpectedTokens.push_back(tok::identifier);
139 ExpectedTokens.push_back(tok::identifier);
140
141 std::vector<Token> toks = CheckLex("#define M(x) x\n"
142 "M(M(i) c)",
143 ExpectedTokens);
144
145 EXPECT_EQ("M(i)", getSourceText(toks[0], toks[0]));
146}
147
148TEST_F(LexerTest, GetSourceTextExpandsInMacroArgumentForBeginOfMacro) {
149 std::vector<tok::TokenKind> ExpectedTokens;
150 ExpectedTokens.push_back(tok::identifier);
151 ExpectedTokens.push_back(tok::identifier);
152 ExpectedTokens.push_back(tok::identifier);
153
154 std::vector<Token> toks = CheckLex("#define M(x) x\n"
155 "M(c c M(i))",
156 ExpectedTokens);
157
158 EXPECT_EQ("c M(i)", getSourceText(toks[1], toks[2]));
159}
160
161TEST_F(LexerTest, GetSourceTextExpandsInMacroArgumentForEndOfMacro) {
162 std::vector<tok::TokenKind> ExpectedTokens;
163 ExpectedTokens.push_back(tok::identifier);
164 ExpectedTokens.push_back(tok::identifier);
165 ExpectedTokens.push_back(tok::identifier);
166
167 std::vector<Token> toks = CheckLex("#define M(x) x\n"
168 "M(M(i) c c)",
169 ExpectedTokens);
170
171 EXPECT_EQ("M(i) c", getSourceText(toks[0], toks[1]));
172}
173
174TEST_F(LexerTest, GetSourceTextInSeparateFnMacros) {
175 std::vector<tok::TokenKind> ExpectedTokens;
176 ExpectedTokens.push_back(tok::identifier);
177 ExpectedTokens.push_back(tok::identifier);
178 ExpectedTokens.push_back(tok::identifier);
179 ExpectedTokens.push_back(tok::identifier);
180
181 std::vector<Token> toks = CheckLex("#define M(x) x\n"
182 "M(c M(i)) M(M(i) c)",
183 ExpectedTokens);
184
185 EXPECT_EQ("<INVALID>", getSourceText(toks[1], toks[2]));
186}
187
188TEST_F(LexerTest, GetSourceTextWorksAcrossTokenPastes) {
189 std::vector<tok::TokenKind> ExpectedTokens;
190 ExpectedTokens.push_back(tok::identifier);
191 ExpectedTokens.push_back(tok::l_paren);
192 ExpectedTokens.push_back(tok::identifier);
193 ExpectedTokens.push_back(tok::r_paren);
194
195 std::vector<Token> toks = CheckLex("#define M(x) x\n"
196 "#define C(x) M(x##c)\n"
197 "M(f(C(i)))",
198 ExpectedTokens);
199
200 EXPECT_EQ("C(i)", getSourceText(toks[2], toks[2]));
201}
202
203TEST_F(LexerTest, GetSourceTextExpandsAcrossMultipleMacroCalls) {
204 std::vector<tok::TokenKind> ExpectedTokens;
205 ExpectedTokens.push_back(tok::identifier);
206 ExpectedTokens.push_back(tok::l_paren);
207 ExpectedTokens.push_back(tok::identifier);
208 ExpectedTokens.push_back(tok::r_paren);
209
210 std::vector<Token> toks = CheckLex("#define M(x) x\n"
211 "f(M(M(i)))",
212 ExpectedTokens);
213 EXPECT_EQ("M(M(i))", getSourceText(toks[2], toks[2]));
214}
215
216TEST_F(LexerTest, GetSourceTextInMiddleOfMacroArgument) {
217 std::vector<tok::TokenKind> ExpectedTokens;
218 ExpectedTokens.push_back(tok::identifier);
219 ExpectedTokens.push_back(tok::l_paren);
220 ExpectedTokens.push_back(tok::identifier);
221 ExpectedTokens.push_back(tok::r_paren);
222
223 std::vector<Token> toks = CheckLex("#define M(x) x\n"
224 "M(f(i))",
225 ExpectedTokens);
226 EXPECT_EQ("i", getSourceText(toks[2], toks[2]));
227}
228
229TEST_F(LexerTest, GetSourceTextExpandsAroundDifferentMacroCalls) {
230 std::vector<tok::TokenKind> ExpectedTokens;
231 ExpectedTokens.push_back(tok::identifier);
232 ExpectedTokens.push_back(tok::l_paren);
233 ExpectedTokens.push_back(tok::identifier);
234 ExpectedTokens.push_back(tok::r_paren);
235
236 std::vector<Token> toks = CheckLex("#define M(x) x\n"
237 "#define C(x) x\n"
238 "f(C(M(i)))",
239 ExpectedTokens);
240 EXPECT_EQ("C(M(i))", getSourceText(toks[2], toks[2]));
241}
242
243TEST_F(LexerTest, GetSourceTextOnlyExpandsIfFirstTokenInMacro) {
244 std::vector<tok::TokenKind> ExpectedTokens;
245 ExpectedTokens.push_back(tok::identifier);
246 ExpectedTokens.push_back(tok::l_paren);
247 ExpectedTokens.push_back(tok::identifier);
248 ExpectedTokens.push_back(tok::identifier);
249 ExpectedTokens.push_back(tok::r_paren);
250
251 std::vector<Token> toks = CheckLex("#define M(x) x\n"
252 "#define C(x) c x\n"
253 "f(C(M(i)))",
254 ExpectedTokens);
255 EXPECT_EQ("M(i)", getSourceText(toks[3], toks[3]));
256}
257
258TEST_F(LexerTest, GetSourceTextExpandsRecursively) {
259 std::vector<tok::TokenKind> ExpectedTokens;
260 ExpectedTokens.push_back(tok::identifier);
261 ExpectedTokens.push_back(tok::identifier);
262 ExpectedTokens.push_back(tok::l_paren);
263 ExpectedTokens.push_back(tok::identifier);
264 ExpectedTokens.push_back(tok::r_paren);
265
266 std::vector<Token> toks = CheckLex("#define M(x) x\n"
267 "#define C(x) c M(x)\n"
268 "C(f(M(i)))",
269 ExpectedTokens);
270 EXPECT_EQ("M(i)", getSourceText(toks[3], toks[3]));
271}
272
273TEST_F(LexerTest, LexAPI) {
274 std::vector<tok::TokenKind> ExpectedTokens;
275 ExpectedTokens.push_back(tok::l_square);
276 ExpectedTokens.push_back(tok::identifier);
277 ExpectedTokens.push_back(tok::r_square);
278 ExpectedTokens.push_back(tok::l_square);
279 ExpectedTokens.push_back(tok::identifier);
280 ExpectedTokens.push_back(tok::r_square);
281 ExpectedTokens.push_back(tok::identifier);
282 ExpectedTokens.push_back(tok::identifier);
283 ExpectedTokens.push_back(tok::identifier);
284 ExpectedTokens.push_back(tok::identifier);
285
286 std::vector<Token> toks = CheckLex("#define M(x) [x]\n"
287 "#define N(x) x\n"
288 "#define INN(x) x\n"
289 "#define NOF1 INN(val)\n"
290 "#define NOF2 val\n"
291 "M(foo) N([bar])\n"
292 "N(INN(val)) N(NOF1) N(NOF2) N(val)",
293 ExpectedTokens);
294
Argyrios Kyrtzidisd1699112012-01-19 15:59:01 +0000295 SourceLocation lsqrLoc = toks[0].getLocation();
296 SourceLocation idLoc = toks[1].getLocation();
297 SourceLocation rsqrLoc = toks[2].getLocation();
Argyrios Kyrtzidisa99e02d2012-01-19 15:59:14 +0000298 std::pair<SourceLocation,SourceLocation>
299 macroPair = SourceMgr.getExpansionRange(lsqrLoc);
300 SourceRange macroRange = SourceRange(macroPair.first, macroPair.second);
301
Argyrios Kyrtzidis1b07c342012-01-19 15:59:08 +0000302 SourceLocation Loc;
303 EXPECT_TRUE(Lexer::isAtStartOfMacroExpansion(lsqrLoc, SourceMgr, LangOpts, &Loc));
Argyrios Kyrtzidisa99e02d2012-01-19 15:59:14 +0000304 EXPECT_EQ(Loc, macroRange.getBegin());
Argyrios Kyrtzidisd1699112012-01-19 15:59:01 +0000305 EXPECT_FALSE(Lexer::isAtStartOfMacroExpansion(idLoc, SourceMgr, LangOpts));
306 EXPECT_FALSE(Lexer::isAtEndOfMacroExpansion(idLoc, SourceMgr, LangOpts));
Argyrios Kyrtzidis1b07c342012-01-19 15:59:08 +0000307 EXPECT_TRUE(Lexer::isAtEndOfMacroExpansion(rsqrLoc, SourceMgr, LangOpts, &Loc));
Argyrios Kyrtzidisa99e02d2012-01-19 15:59:14 +0000308 EXPECT_EQ(Loc, macroRange.getEnd());
309
Argyrios Kyrtzidis0d9e24b2012-02-03 05:58:29 +0000310 CharSourceRange range = Lexer::makeFileCharRange(
311 CharSourceRange::getTokenRange(lsqrLoc, idLoc), SourceMgr, LangOpts);
Argyrios Kyrtzidisa99e02d2012-01-19 15:59:14 +0000312 EXPECT_TRUE(range.isInvalid());
Argyrios Kyrtzidis0d9e24b2012-02-03 05:58:29 +0000313 range = Lexer::makeFileCharRange(CharSourceRange::getTokenRange(idLoc, rsqrLoc),
Argyrios Kyrtzidisa99e02d2012-01-19 15:59:14 +0000314 SourceMgr, LangOpts);
315 EXPECT_TRUE(range.isInvalid());
Argyrios Kyrtzidis0d9e24b2012-02-03 05:58:29 +0000316 range = Lexer::makeFileCharRange(CharSourceRange::getTokenRange(lsqrLoc, rsqrLoc),
Argyrios Kyrtzidisa99e02d2012-01-19 15:59:14 +0000317 SourceMgr, LangOpts);
318 EXPECT_TRUE(!range.isTokenRange());
319 EXPECT_EQ(range.getAsRange(),
320 SourceRange(macroRange.getBegin(),
321 macroRange.getEnd().getLocWithOffset(1)));
Argyrios Kyrtzidis7838a2b2012-01-19 15:59:19 +0000322
323 StringRef text = Lexer::getSourceText(
Argyrios Kyrtzidis0d9e24b2012-02-03 05:58:29 +0000324 CharSourceRange::getTokenRange(lsqrLoc, rsqrLoc),
325 SourceMgr, LangOpts);
Argyrios Kyrtzidis7838a2b2012-01-19 15:59:19 +0000326 EXPECT_EQ(text, "M(foo)");
Argyrios Kyrtzidis85e76712012-01-20 16:52:43 +0000327
328 SourceLocation macroLsqrLoc = toks[3].getLocation();
329 SourceLocation macroIdLoc = toks[4].getLocation();
330 SourceLocation macroRsqrLoc = toks[5].getLocation();
331 SourceLocation fileLsqrLoc = SourceMgr.getSpellingLoc(macroLsqrLoc);
332 SourceLocation fileIdLoc = SourceMgr.getSpellingLoc(macroIdLoc);
333 SourceLocation fileRsqrLoc = SourceMgr.getSpellingLoc(macroRsqrLoc);
334
Argyrios Kyrtzidis0d9e24b2012-02-03 05:58:29 +0000335 range = Lexer::makeFileCharRange(
336 CharSourceRange::getTokenRange(macroLsqrLoc, macroIdLoc),
337 SourceMgr, LangOpts);
Argyrios Kyrtzidis85e76712012-01-20 16:52:43 +0000338 EXPECT_EQ(SourceRange(fileLsqrLoc, fileIdLoc.getLocWithOffset(3)),
339 range.getAsRange());
340
Argyrios Kyrtzidis0d9e24b2012-02-03 05:58:29 +0000341 range = Lexer::makeFileCharRange(CharSourceRange::getTokenRange(macroIdLoc, macroRsqrLoc),
Argyrios Kyrtzidis85e76712012-01-20 16:52:43 +0000342 SourceMgr, LangOpts);
343 EXPECT_EQ(SourceRange(fileIdLoc, fileRsqrLoc.getLocWithOffset(1)),
344 range.getAsRange());
345
346 macroPair = SourceMgr.getExpansionRange(macroLsqrLoc);
Argyrios Kyrtzidis0d9e24b2012-02-03 05:58:29 +0000347 range = Lexer::makeFileCharRange(
348 CharSourceRange::getTokenRange(macroLsqrLoc, macroRsqrLoc),
349 SourceMgr, LangOpts);
Argyrios Kyrtzidis85e76712012-01-20 16:52:43 +0000350 EXPECT_EQ(SourceRange(macroPair.first, macroPair.second.getLocWithOffset(1)),
351 range.getAsRange());
352
353 text = Lexer::getSourceText(
354 CharSourceRange::getTokenRange(SourceRange(macroLsqrLoc, macroIdLoc)),
355 SourceMgr, LangOpts);
356 EXPECT_EQ(text, "[bar");
Argyrios Kyrtzidisabff5f12012-01-23 16:58:33 +0000357
358
359 SourceLocation idLoc1 = toks[6].getLocation();
360 SourceLocation idLoc2 = toks[7].getLocation();
361 SourceLocation idLoc3 = toks[8].getLocation();
362 SourceLocation idLoc4 = toks[9].getLocation();
363 EXPECT_EQ("INN", Lexer::getImmediateMacroName(idLoc1, SourceMgr, LangOpts));
364 EXPECT_EQ("INN", Lexer::getImmediateMacroName(idLoc2, SourceMgr, LangOpts));
365 EXPECT_EQ("NOF2", Lexer::getImmediateMacroName(idLoc3, SourceMgr, LangOpts));
366 EXPECT_EQ("N", Lexer::getImmediateMacroName(idLoc4, SourceMgr, LangOpts));
Argyrios Kyrtzidisd1699112012-01-19 15:59:01 +0000367}
368
Vedant Kumar95a2a7f2016-05-19 23:44:02 +0000369TEST_F(LexerTest, DontMergeMacroArgsFromDifferentMacroFiles) {
370 std::vector<Token> toks =
371 Lex("#define helper1 0\n"
372 "void helper2(const char *, ...);\n"
373 "#define M1(a, ...) helper2(a, ##__VA_ARGS__)\n"
374 "#define M2(a, ...) M1(a, helper1, ##__VA_ARGS__)\n"
375 "void f1() { M2(\"a\", \"b\"); }");
376
377 // Check the file corresponding to the "helper1" macro arg in M2.
378 //
379 // The lexer used to report its size as 31, meaning that the end of the
380 // expansion would be on the *next line* (just past `M2("a", "b")`). Make
381 // sure that we get the correct end location (the comma after "helper1").
382 SourceLocation helper1ArgLoc = toks[20].getLocation();
383 EXPECT_EQ(SourceMgr.getFileIDSize(SourceMgr.getFileID(helper1ArgLoc)), 8U);
384}
385
Argyrios Kyrtzidisd1699112012-01-19 15:59:01 +0000386} // anonymous namespace