1//===- unittests/Basic/LexerTest.cpp ------ Lexer tests -------------------===//
2//
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
10#include "clang/Basic/SourceManager.h"
11#include "clang/Basic/FileManager.h"
12#include "clang/Basic/Diagnostic.h"
13#include "clang/Basic/LangOptions.h"
14#include "clang/Basic/TargetOptions.h"
15#include "clang/Basic/TargetInfo.h"
16#include "clang/Lex/ModuleLoader.h"
17#include "clang/Lex/HeaderSearch.h"
18#include "clang/Lex/Preprocessor.h"
19#include "llvm/Config/config.h"
20
21#include "gtest/gtest.h"
22
23using namespace llvm;
24using namespace clang;
25
26namespace {
27
28// The test fixture.
29class LexerTest : public ::testing::Test {
30protected:
31  LexerTest()
32    : FileMgr(FileMgrOpts),
33      DiagID(new DiagnosticIDs()),
34      Diags(DiagID, new IgnoringDiagConsumer()),
35      SourceMgr(Diags, FileMgr) {
36    TargetOpts.Triple = "x86_64-apple-darwin11.1.0";
37    Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
38  }
39
40  FileSystemOptions FileMgrOpts;
41  FileManager FileMgr;
42  IntrusiveRefCntPtr<DiagnosticIDs> DiagID;
43  DiagnosticsEngine Diags;
44  SourceManager SourceMgr;
45  LangOptions LangOpts;
46  TargetOptions TargetOpts;
47  IntrusiveRefCntPtr<TargetInfo> Target;
48};
49
50class VoidModuleLoader : public ModuleLoader {
51  virtual Module *loadModule(SourceLocation ImportLoc, ModuleIdPath Path,
52                             Module::NameVisibilityKind Visibility,
53                             bool IsInclusionDirective) {
54    return 0;
55  }
56};
57
58TEST_F(LexerTest, LexAPI) {
59  const char *source =
60    "#define M(x) [x]\n"
61    "#define N(x) x\n"
62    "#define INN(x) x\n"
63    "#define NOF1 INN(val)\n"
64    "#define NOF2 val\n"
65    "M(foo) N([bar])\n"
66    "N(INN(val)) N(NOF1) N(NOF2) N(val)";
67
68  MemoryBuffer *buf = MemoryBuffer::getMemBuffer(source);
69  (void)SourceMgr.createMainFileIDForMemBuffer(buf);
70
71  VoidModuleLoader ModLoader;
72  HeaderSearch HeaderInfo(FileMgr, Diags, LangOpts, Target.getPtr());
73  Preprocessor PP(Diags, LangOpts,
74                  Target.getPtr(),
75                  SourceMgr, HeaderInfo, ModLoader,
76                  /*IILookup =*/ 0,
77                  /*OwnsHeaderSearch =*/false,
78                  /*DelayInitialization =*/ false);
79  PP.EnterMainSourceFile();
80
81  std::vector<Token> toks;
82  while (1) {
83    Token tok;
84    PP.Lex(tok);
85    if (tok.is(tok::eof))
86      break;
87    toks.push_back(tok);
88  }
89
90  // Make sure we got the tokens that we expected.
91  ASSERT_EQ(10U, toks.size());
92  ASSERT_EQ(tok::l_square, toks[0].getKind());
93  ASSERT_EQ(tok::identifier, toks[1].getKind());
94  ASSERT_EQ(tok::r_square, toks[2].getKind());
95  ASSERT_EQ(tok::l_square, toks[3].getKind());
96  ASSERT_EQ(tok::identifier, toks[4].getKind());
97  ASSERT_EQ(tok::r_square, toks[5].getKind());
98  ASSERT_EQ(tok::identifier, toks[6].getKind());
99  ASSERT_EQ(tok::identifier, toks[7].getKind());
100  ASSERT_EQ(tok::identifier, toks[8].getKind());
101  ASSERT_EQ(tok::identifier, toks[9].getKind());
102
103  SourceLocation lsqrLoc = toks[0].getLocation();
104  SourceLocation idLoc = toks[1].getLocation();
105  SourceLocation rsqrLoc = toks[2].getLocation();
106  std::pair<SourceLocation,SourceLocation>
107    macroPair = SourceMgr.getExpansionRange(lsqrLoc);
108  SourceRange macroRange = SourceRange(macroPair.first, macroPair.second);
109
110  SourceLocation Loc;
111  EXPECT_TRUE(Lexer::isAtStartOfMacroExpansion(lsqrLoc, SourceMgr, LangOpts, &Loc));
112  EXPECT_EQ(Loc, macroRange.getBegin());
113  EXPECT_FALSE(Lexer::isAtStartOfMacroExpansion(idLoc, SourceMgr, LangOpts));
114  EXPECT_FALSE(Lexer::isAtEndOfMacroExpansion(idLoc, SourceMgr, LangOpts));
115  EXPECT_TRUE(Lexer::isAtEndOfMacroExpansion(rsqrLoc, SourceMgr, LangOpts, &Loc));
116  EXPECT_EQ(Loc, macroRange.getEnd());
117
118  CharSourceRange range = Lexer::makeFileCharRange(
119           CharSourceRange::getTokenRange(lsqrLoc, idLoc), SourceMgr, LangOpts);
120  EXPECT_TRUE(range.isInvalid());
121  range = Lexer::makeFileCharRange(CharSourceRange::getTokenRange(idLoc, rsqrLoc),
122                                   SourceMgr, LangOpts);
123  EXPECT_TRUE(range.isInvalid());
124  range = Lexer::makeFileCharRange(CharSourceRange::getTokenRange(lsqrLoc, rsqrLoc),
125                                   SourceMgr, LangOpts);
126  EXPECT_TRUE(!range.isTokenRange());
127  EXPECT_EQ(range.getAsRange(),
128            SourceRange(macroRange.getBegin(),
129                        macroRange.getEnd().getLocWithOffset(1)));
130
131  StringRef text = Lexer::getSourceText(
132                               CharSourceRange::getTokenRange(lsqrLoc, rsqrLoc),
133                               SourceMgr, LangOpts);
134  EXPECT_EQ(text, "M(foo)");
135
136  SourceLocation macroLsqrLoc = toks[3].getLocation();
137  SourceLocation macroIdLoc = toks[4].getLocation();
138  SourceLocation macroRsqrLoc = toks[5].getLocation();
139  SourceLocation fileLsqrLoc = SourceMgr.getSpellingLoc(macroLsqrLoc);
140  SourceLocation fileIdLoc = SourceMgr.getSpellingLoc(macroIdLoc);
141  SourceLocation fileRsqrLoc = SourceMgr.getSpellingLoc(macroRsqrLoc);
142
143  range = Lexer::makeFileCharRange(
144      CharSourceRange::getTokenRange(macroLsqrLoc, macroIdLoc),
145      SourceMgr, LangOpts);
146  EXPECT_EQ(SourceRange(fileLsqrLoc, fileIdLoc.getLocWithOffset(3)),
147            range.getAsRange());
148
149  range = Lexer::makeFileCharRange(CharSourceRange::getTokenRange(macroIdLoc, macroRsqrLoc),
150                                   SourceMgr, LangOpts);
151  EXPECT_EQ(SourceRange(fileIdLoc, fileRsqrLoc.getLocWithOffset(1)),
152            range.getAsRange());
153
154  macroPair = SourceMgr.getExpansionRange(macroLsqrLoc);
155  range = Lexer::makeFileCharRange(
156                     CharSourceRange::getTokenRange(macroLsqrLoc, macroRsqrLoc),
157                     SourceMgr, LangOpts);
158  EXPECT_EQ(SourceRange(macroPair.first, macroPair.second.getLocWithOffset(1)),
159            range.getAsRange());
160
161  text = Lexer::getSourceText(
162          CharSourceRange::getTokenRange(SourceRange(macroLsqrLoc, macroIdLoc)),
163          SourceMgr, LangOpts);
164  EXPECT_EQ(text, "[bar");
165
166
167  SourceLocation idLoc1 = toks[6].getLocation();
168  SourceLocation idLoc2 = toks[7].getLocation();
169  SourceLocation idLoc3 = toks[8].getLocation();
170  SourceLocation idLoc4 = toks[9].getLocation();
171  EXPECT_EQ("INN", Lexer::getImmediateMacroName(idLoc1, SourceMgr, LangOpts));
172  EXPECT_EQ("INN", Lexer::getImmediateMacroName(idLoc2, SourceMgr, LangOpts));
173  EXPECT_EQ("NOF2", Lexer::getImmediateMacroName(idLoc3, SourceMgr, LangOpts));
174  EXPECT_EQ("N", Lexer::getImmediateMacroName(idLoc4, SourceMgr, LangOpts));
175}
176
177} // anonymous namespace
178