blob: a8e25cb2a394cceb7b21344438deb153019dab92 [file] [log] [blame]
Chandler Carruth1050e8b2012-12-04 09:45:34 +00001//===- unittests/Lex/LexerTest.cpp ------ Lexer tests ---------------------===//
Argyrios Kyrtzidis19d5aea2012-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 Carruth1050e8b2012-12-04 09:45:34 +000010#include "clang/Lex/Lexer.h"
Argyrios Kyrtzidis19d5aea2012-01-19 15:59:01 +000011#include "clang/Basic/Diagnostic.h"
Douglas Gregor3aeb34f2012-10-23 22:38:58 +000012#include "clang/Basic/DiagnosticOptions.h"
Chandler Carruth1050e8b2012-12-04 09:45:34 +000013#include "clang/Basic/FileManager.h"
Argyrios Kyrtzidis19d5aea2012-01-19 15:59:01 +000014#include "clang/Basic/LangOptions.h"
Chandler Carruth7cc315c2012-12-04 09:53:37 +000015#include "clang/Basic/SourceManager.h"
Argyrios Kyrtzidis19d5aea2012-01-19 15:59:01 +000016#include "clang/Basic/TargetInfo.h"
Chandler Carruth1050e8b2012-12-04 09:45:34 +000017#include "clang/Basic/TargetOptions.h"
Argyrios Kyrtzidis19d5aea2012-01-19 15:59:01 +000018#include "clang/Lex/HeaderSearch.h"
Douglas Gregorb0985c82012-10-24 16:24:38 +000019#include "clang/Lex/HeaderSearchOptions.h"
Chandler Carruth1050e8b2012-12-04 09:45:34 +000020#include "clang/Lex/ModuleLoader.h"
Argyrios Kyrtzidis19d5aea2012-01-19 15:59:01 +000021#include "clang/Lex/Preprocessor.h"
Douglas Gregor36a16492012-10-24 17:46:57 +000022#include "clang/Lex/PreprocessorOptions.h"
Argyrios Kyrtzidis19d5aea2012-01-19 15:59:01 +000023#include "llvm/Config/config.h"
Argyrios Kyrtzidis19d5aea2012-01-19 15:59:01 +000024#include "gtest/gtest.h"
25
26using namespace llvm;
27using namespace clang;
28
29namespace {
30
Argyrios Kyrtzidis19d5aea2012-01-19 15:59:01 +000031class VoidModuleLoader : public ModuleLoader {
Douglas Gregor7dff05b2012-11-30 00:01:57 +000032 virtual ModuleLoadResult loadModule(SourceLocation ImportLoc,
33 ModuleIdPath Path,
34 Module::NameVisibilityKind Visibility,
35 bool IsInclusionDirective) {
36 return ModuleLoadResult();
Argyrios Kyrtzidis19d5aea2012-01-19 15:59:01 +000037 }
NAKAMURA Takumi1a4191d2013-01-12 02:16:29 +000038
39 virtual void makeModuleVisible(Module *Mod,
Argyrios Kyrtzidis5ebcb202013-02-01 16:36:12 +000040 Module::NameVisibilityKind Visibility,
Douglas Gregor906d66a2013-03-20 21:10:35 +000041 SourceLocation ImportLoc,
42 bool Complain) { }
Argyrios Kyrtzidis19d5aea2012-01-19 15:59:01 +000043};
44
Argyrios Kyrtzidisc50c6ff2013-05-16 21:37:39 +000045// The test fixture.
46class LexerTest : public ::testing::Test {
47protected:
48 LexerTest()
49 : FileMgr(FileMgrOpts),
50 DiagID(new DiagnosticIDs()),
51 Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()),
52 SourceMgr(Diags, FileMgr),
53 TargetOpts(new TargetOptions)
54 {
55 TargetOpts->Triple = "x86_64-apple-darwin11.1.0";
56 Target = TargetInfo::CreateTargetInfo(Diags, &*TargetOpts);
Argyrios Kyrtzidis19d5aea2012-01-19 15:59:01 +000057 }
58
Argyrios Kyrtzidisc50c6ff2013-05-16 21:37:39 +000059 std::vector<Token> CheckLex(StringRef Source,
60 ArrayRef<tok::TokenKind> ExpectedTokens) {
61 MemoryBuffer *buf = MemoryBuffer::getMemBuffer(Source);
62 (void) SourceMgr.createMainFileIDForMemBuffer(buf);
63
64 VoidModuleLoader ModLoader;
65 HeaderSearch HeaderInfo(new HeaderSearchOptions, FileMgr, Diags, LangOpts,
66 Target.getPtr());
67 Preprocessor PP(new PreprocessorOptions(), Diags, LangOpts, Target.getPtr(),
68 SourceMgr, HeaderInfo, ModLoader, /*IILookup =*/ 0,
69 /*OwnsHeaderSearch =*/ false,
70 /*DelayInitialization =*/ false);
71 PP.EnterMainSourceFile();
72
73 std::vector<Token> toks;
74 while (1) {
75 Token tok;
76 PP.Lex(tok);
77 if (tok.is(tok::eof))
78 break;
79 toks.push_back(tok);
80 }
81
82 EXPECT_EQ(ExpectedTokens.size(), toks.size());
83 for (unsigned i = 0, e = ExpectedTokens.size(); i != e; ++i) {
84 EXPECT_EQ(ExpectedTokens[i], toks[i].getKind());
85 }
86
87 return toks;
88 }
89
90 std::string getSourceText(Token Begin, Token End) {
91 bool Invalid;
92 StringRef Str =
93 Lexer::getSourceText(CharSourceRange::getTokenRange(SourceRange(
94 Begin.getLocation(), End.getLocation())),
95 SourceMgr, LangOpts, &Invalid);
96 if (Invalid)
97 return "<INVALID>";
98 return Str;
99 }
100
101 FileSystemOptions FileMgrOpts;
102 FileManager FileMgr;
103 IntrusiveRefCntPtr<DiagnosticIDs> DiagID;
104 DiagnosticsEngine Diags;
105 SourceManager SourceMgr;
106 LangOptions LangOpts;
107 IntrusiveRefCntPtr<TargetOptions> TargetOpts;
108 IntrusiveRefCntPtr<TargetInfo> Target;
109};
110
111TEST_F(LexerTest, GetSourceTextExpandsToMaximumInMacroArgument) {
112 std::vector<tok::TokenKind> ExpectedTokens;
113 ExpectedTokens.push_back(tok::identifier);
114 ExpectedTokens.push_back(tok::l_paren);
115 ExpectedTokens.push_back(tok::identifier);
116 ExpectedTokens.push_back(tok::r_paren);
117
118 std::vector<Token> toks = CheckLex("#define M(x) x\n"
119 "M(f(M(i)))",
120 ExpectedTokens);
121
122 EXPECT_EQ("M(i)", getSourceText(toks[2], toks[2]));
123}
124
125TEST_F(LexerTest, GetSourceTextExpandsToMaximumInMacroArgumentForEndOfMacro) {
126 std::vector<tok::TokenKind> ExpectedTokens;
127 ExpectedTokens.push_back(tok::identifier);
128 ExpectedTokens.push_back(tok::identifier);
129
130 std::vector<Token> toks = CheckLex("#define M(x) x\n"
131 "M(M(i) c)",
132 ExpectedTokens);
133
134 EXPECT_EQ("M(i)", getSourceText(toks[0], toks[0]));
135}
136
137TEST_F(LexerTest, GetSourceTextExpandsInMacroArgumentForBeginOfMacro) {
138 std::vector<tok::TokenKind> ExpectedTokens;
139 ExpectedTokens.push_back(tok::identifier);
140 ExpectedTokens.push_back(tok::identifier);
141 ExpectedTokens.push_back(tok::identifier);
142
143 std::vector<Token> toks = CheckLex("#define M(x) x\n"
144 "M(c c M(i))",
145 ExpectedTokens);
146
147 EXPECT_EQ("c M(i)", getSourceText(toks[1], toks[2]));
148}
149
150TEST_F(LexerTest, GetSourceTextExpandsInMacroArgumentForEndOfMacro) {
151 std::vector<tok::TokenKind> ExpectedTokens;
152 ExpectedTokens.push_back(tok::identifier);
153 ExpectedTokens.push_back(tok::identifier);
154 ExpectedTokens.push_back(tok::identifier);
155
156 std::vector<Token> toks = CheckLex("#define M(x) x\n"
157 "M(M(i) c c)",
158 ExpectedTokens);
159
160 EXPECT_EQ("M(i) c", getSourceText(toks[0], toks[1]));
161}
162
163TEST_F(LexerTest, GetSourceTextInSeparateFnMacros) {
164 std::vector<tok::TokenKind> ExpectedTokens;
165 ExpectedTokens.push_back(tok::identifier);
166 ExpectedTokens.push_back(tok::identifier);
167 ExpectedTokens.push_back(tok::identifier);
168 ExpectedTokens.push_back(tok::identifier);
169
170 std::vector<Token> toks = CheckLex("#define M(x) x\n"
171 "M(c M(i)) M(M(i) c)",
172 ExpectedTokens);
173
174 EXPECT_EQ("<INVALID>", getSourceText(toks[1], toks[2]));
175}
176
177TEST_F(LexerTest, GetSourceTextWorksAcrossTokenPastes) {
178 std::vector<tok::TokenKind> ExpectedTokens;
179 ExpectedTokens.push_back(tok::identifier);
180 ExpectedTokens.push_back(tok::l_paren);
181 ExpectedTokens.push_back(tok::identifier);
182 ExpectedTokens.push_back(tok::r_paren);
183
184 std::vector<Token> toks = CheckLex("#define M(x) x\n"
185 "#define C(x) M(x##c)\n"
186 "M(f(C(i)))",
187 ExpectedTokens);
188
189 EXPECT_EQ("C(i)", getSourceText(toks[2], toks[2]));
190}
191
192TEST_F(LexerTest, GetSourceTextExpandsAcrossMultipleMacroCalls) {
193 std::vector<tok::TokenKind> ExpectedTokens;
194 ExpectedTokens.push_back(tok::identifier);
195 ExpectedTokens.push_back(tok::l_paren);
196 ExpectedTokens.push_back(tok::identifier);
197 ExpectedTokens.push_back(tok::r_paren);
198
199 std::vector<Token> toks = CheckLex("#define M(x) x\n"
200 "f(M(M(i)))",
201 ExpectedTokens);
202 EXPECT_EQ("M(M(i))", getSourceText(toks[2], toks[2]));
203}
204
205TEST_F(LexerTest, GetSourceTextInMiddleOfMacroArgument) {
206 std::vector<tok::TokenKind> ExpectedTokens;
207 ExpectedTokens.push_back(tok::identifier);
208 ExpectedTokens.push_back(tok::l_paren);
209 ExpectedTokens.push_back(tok::identifier);
210 ExpectedTokens.push_back(tok::r_paren);
211
212 std::vector<Token> toks = CheckLex("#define M(x) x\n"
213 "M(f(i))",
214 ExpectedTokens);
215 EXPECT_EQ("i", getSourceText(toks[2], toks[2]));
216}
217
218TEST_F(LexerTest, GetSourceTextExpandsAroundDifferentMacroCalls) {
219 std::vector<tok::TokenKind> ExpectedTokens;
220 ExpectedTokens.push_back(tok::identifier);
221 ExpectedTokens.push_back(tok::l_paren);
222 ExpectedTokens.push_back(tok::identifier);
223 ExpectedTokens.push_back(tok::r_paren);
224
225 std::vector<Token> toks = CheckLex("#define M(x) x\n"
226 "#define C(x) x\n"
227 "f(C(M(i)))",
228 ExpectedTokens);
229 EXPECT_EQ("C(M(i))", getSourceText(toks[2], toks[2]));
230}
231
232TEST_F(LexerTest, GetSourceTextOnlyExpandsIfFirstTokenInMacro) {
233 std::vector<tok::TokenKind> ExpectedTokens;
234 ExpectedTokens.push_back(tok::identifier);
235 ExpectedTokens.push_back(tok::l_paren);
236 ExpectedTokens.push_back(tok::identifier);
237 ExpectedTokens.push_back(tok::identifier);
238 ExpectedTokens.push_back(tok::r_paren);
239
240 std::vector<Token> toks = CheckLex("#define M(x) x\n"
241 "#define C(x) c x\n"
242 "f(C(M(i)))",
243 ExpectedTokens);
244 EXPECT_EQ("M(i)", getSourceText(toks[3], toks[3]));
245}
246
247TEST_F(LexerTest, GetSourceTextExpandsRecursively) {
248 std::vector<tok::TokenKind> ExpectedTokens;
249 ExpectedTokens.push_back(tok::identifier);
250 ExpectedTokens.push_back(tok::identifier);
251 ExpectedTokens.push_back(tok::l_paren);
252 ExpectedTokens.push_back(tok::identifier);
253 ExpectedTokens.push_back(tok::r_paren);
254
255 std::vector<Token> toks = CheckLex("#define M(x) x\n"
256 "#define C(x) c M(x)\n"
257 "C(f(M(i)))",
258 ExpectedTokens);
259 EXPECT_EQ("M(i)", getSourceText(toks[3], toks[3]));
260}
261
262TEST_F(LexerTest, LexAPI) {
263 std::vector<tok::TokenKind> ExpectedTokens;
264 ExpectedTokens.push_back(tok::l_square);
265 ExpectedTokens.push_back(tok::identifier);
266 ExpectedTokens.push_back(tok::r_square);
267 ExpectedTokens.push_back(tok::l_square);
268 ExpectedTokens.push_back(tok::identifier);
269 ExpectedTokens.push_back(tok::r_square);
270 ExpectedTokens.push_back(tok::identifier);
271 ExpectedTokens.push_back(tok::identifier);
272 ExpectedTokens.push_back(tok::identifier);
273 ExpectedTokens.push_back(tok::identifier);
274
275 std::vector<Token> toks = CheckLex("#define M(x) [x]\n"
276 "#define N(x) x\n"
277 "#define INN(x) x\n"
278 "#define NOF1 INN(val)\n"
279 "#define NOF2 val\n"
280 "M(foo) N([bar])\n"
281 "N(INN(val)) N(NOF1) N(NOF2) N(val)",
282 ExpectedTokens);
283
Argyrios Kyrtzidis19d5aea2012-01-19 15:59:01 +0000284 SourceLocation lsqrLoc = toks[0].getLocation();
285 SourceLocation idLoc = toks[1].getLocation();
286 SourceLocation rsqrLoc = toks[2].getLocation();
Argyrios Kyrtzidis11b652d2012-01-19 15:59:14 +0000287 std::pair<SourceLocation,SourceLocation>
288 macroPair = SourceMgr.getExpansionRange(lsqrLoc);
289 SourceRange macroRange = SourceRange(macroPair.first, macroPair.second);
290
Argyrios Kyrtzidis69bda4c2012-01-19 15:59:08 +0000291 SourceLocation Loc;
292 EXPECT_TRUE(Lexer::isAtStartOfMacroExpansion(lsqrLoc, SourceMgr, LangOpts, &Loc));
Argyrios Kyrtzidis11b652d2012-01-19 15:59:14 +0000293 EXPECT_EQ(Loc, macroRange.getBegin());
Argyrios Kyrtzidis19d5aea2012-01-19 15:59:01 +0000294 EXPECT_FALSE(Lexer::isAtStartOfMacroExpansion(idLoc, SourceMgr, LangOpts));
295 EXPECT_FALSE(Lexer::isAtEndOfMacroExpansion(idLoc, SourceMgr, LangOpts));
Argyrios Kyrtzidis69bda4c2012-01-19 15:59:08 +0000296 EXPECT_TRUE(Lexer::isAtEndOfMacroExpansion(rsqrLoc, SourceMgr, LangOpts, &Loc));
Argyrios Kyrtzidis11b652d2012-01-19 15:59:14 +0000297 EXPECT_EQ(Loc, macroRange.getEnd());
298
Argyrios Kyrtzidisa83f4d22012-02-03 05:58:29 +0000299 CharSourceRange range = Lexer::makeFileCharRange(
300 CharSourceRange::getTokenRange(lsqrLoc, idLoc), SourceMgr, LangOpts);
Argyrios Kyrtzidis11b652d2012-01-19 15:59:14 +0000301 EXPECT_TRUE(range.isInvalid());
Argyrios Kyrtzidisa83f4d22012-02-03 05:58:29 +0000302 range = Lexer::makeFileCharRange(CharSourceRange::getTokenRange(idLoc, rsqrLoc),
Argyrios Kyrtzidis11b652d2012-01-19 15:59:14 +0000303 SourceMgr, LangOpts);
304 EXPECT_TRUE(range.isInvalid());
Argyrios Kyrtzidisa83f4d22012-02-03 05:58:29 +0000305 range = Lexer::makeFileCharRange(CharSourceRange::getTokenRange(lsqrLoc, rsqrLoc),
Argyrios Kyrtzidis11b652d2012-01-19 15:59:14 +0000306 SourceMgr, LangOpts);
307 EXPECT_TRUE(!range.isTokenRange());
308 EXPECT_EQ(range.getAsRange(),
309 SourceRange(macroRange.getBegin(),
310 macroRange.getEnd().getLocWithOffset(1)));
Argyrios Kyrtzidise64d9032012-01-19 15:59:19 +0000311
312 StringRef text = Lexer::getSourceText(
Argyrios Kyrtzidisa83f4d22012-02-03 05:58:29 +0000313 CharSourceRange::getTokenRange(lsqrLoc, rsqrLoc),
314 SourceMgr, LangOpts);
Argyrios Kyrtzidise64d9032012-01-19 15:59:19 +0000315 EXPECT_EQ(text, "M(foo)");
Argyrios Kyrtzidisd9806c92012-01-20 16:52:43 +0000316
317 SourceLocation macroLsqrLoc = toks[3].getLocation();
318 SourceLocation macroIdLoc = toks[4].getLocation();
319 SourceLocation macroRsqrLoc = toks[5].getLocation();
320 SourceLocation fileLsqrLoc = SourceMgr.getSpellingLoc(macroLsqrLoc);
321 SourceLocation fileIdLoc = SourceMgr.getSpellingLoc(macroIdLoc);
322 SourceLocation fileRsqrLoc = SourceMgr.getSpellingLoc(macroRsqrLoc);
323
Argyrios Kyrtzidisa83f4d22012-02-03 05:58:29 +0000324 range = Lexer::makeFileCharRange(
325 CharSourceRange::getTokenRange(macroLsqrLoc, macroIdLoc),
326 SourceMgr, LangOpts);
Argyrios Kyrtzidisd9806c92012-01-20 16:52:43 +0000327 EXPECT_EQ(SourceRange(fileLsqrLoc, fileIdLoc.getLocWithOffset(3)),
328 range.getAsRange());
329
Argyrios Kyrtzidisa83f4d22012-02-03 05:58:29 +0000330 range = Lexer::makeFileCharRange(CharSourceRange::getTokenRange(macroIdLoc, macroRsqrLoc),
Argyrios Kyrtzidisd9806c92012-01-20 16:52:43 +0000331 SourceMgr, LangOpts);
332 EXPECT_EQ(SourceRange(fileIdLoc, fileRsqrLoc.getLocWithOffset(1)),
333 range.getAsRange());
334
335 macroPair = SourceMgr.getExpansionRange(macroLsqrLoc);
Argyrios Kyrtzidisa83f4d22012-02-03 05:58:29 +0000336 range = Lexer::makeFileCharRange(
337 CharSourceRange::getTokenRange(macroLsqrLoc, macroRsqrLoc),
338 SourceMgr, LangOpts);
Argyrios Kyrtzidisd9806c92012-01-20 16:52:43 +0000339 EXPECT_EQ(SourceRange(macroPair.first, macroPair.second.getLocWithOffset(1)),
340 range.getAsRange());
341
342 text = Lexer::getSourceText(
343 CharSourceRange::getTokenRange(SourceRange(macroLsqrLoc, macroIdLoc)),
344 SourceMgr, LangOpts);
345 EXPECT_EQ(text, "[bar");
Argyrios Kyrtzidis7f6cf972012-01-23 16:58:33 +0000346
347
348 SourceLocation idLoc1 = toks[6].getLocation();
349 SourceLocation idLoc2 = toks[7].getLocation();
350 SourceLocation idLoc3 = toks[8].getLocation();
351 SourceLocation idLoc4 = toks[9].getLocation();
352 EXPECT_EQ("INN", Lexer::getImmediateMacroName(idLoc1, SourceMgr, LangOpts));
353 EXPECT_EQ("INN", Lexer::getImmediateMacroName(idLoc2, SourceMgr, LangOpts));
354 EXPECT_EQ("NOF2", Lexer::getImmediateMacroName(idLoc3, SourceMgr, LangOpts));
355 EXPECT_EQ("N", Lexer::getImmediateMacroName(idLoc4, SourceMgr, LangOpts));
Argyrios Kyrtzidis19d5aea2012-01-19 15:59:01 +0000356}
357
358} // anonymous namespace