Home | History | Annotate | Download | only in Lex
      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 
     23 using namespace llvm;
     24 using namespace clang;
     25 
     26 namespace {
     27 
     28 // The test fixture.
     29 class LexerTest : public ::testing::Test {
     30 protected:
     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 
     50 class VoidModuleLoader : public ModuleLoader {
     51   virtual Module *loadModule(SourceLocation ImportLoc, ModuleIdPath Path,
     52                              Module::NameVisibilityKind Visibility,
     53                              bool IsInclusionDirective) {
     54     return 0;
     55   }
     56 };
     57 
     58 TEST_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