1//===- unittests/Lex/PPConditionalDirectiveRecordTest.cpp-PP directive 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/Lex/PPConditionalDirectiveRecord.h"
11#include "clang/Basic/Diagnostic.h"
12#include "clang/Basic/DiagnosticOptions.h"
13#include "clang/Basic/FileManager.h"
14#include "clang/Basic/LangOptions.h"
15#include "clang/Basic/SourceManager.h"
16#include "clang/Basic/TargetInfo.h"
17#include "clang/Basic/TargetOptions.h"
18#include "clang/Lex/HeaderSearch.h"
19#include "clang/Lex/HeaderSearchOptions.h"
20#include "clang/Lex/ModuleLoader.h"
21#include "clang/Lex/Preprocessor.h"
22#include "clang/Lex/PreprocessorOptions.h"
23#include "gtest/gtest.h"
24
25using namespace llvm;
26using namespace clang;
27
28namespace {
29
30// The test fixture.
31class PPConditionalDirectiveRecordTest : public ::testing::Test {
32protected:
33  PPConditionalDirectiveRecordTest()
34    : FileMgr(FileMgrOpts),
35      DiagID(new DiagnosticIDs()),
36      Diags(DiagID, new DiagnosticOptions, new IgnoringDiagConsumer()),
37      SourceMgr(Diags, FileMgr),
38      TargetOpts(new TargetOptions)
39  {
40    TargetOpts->Triple = "x86_64-apple-darwin11.1.0";
41    Target = TargetInfo::CreateTargetInfo(Diags, TargetOpts);
42  }
43
44  FileSystemOptions FileMgrOpts;
45  FileManager FileMgr;
46  IntrusiveRefCntPtr<DiagnosticIDs> DiagID;
47  DiagnosticsEngine Diags;
48  SourceManager SourceMgr;
49  LangOptions LangOpts;
50  std::shared_ptr<TargetOptions> TargetOpts;
51  IntrusiveRefCntPtr<TargetInfo> Target;
52};
53
54class VoidModuleLoader : public ModuleLoader {
55  ModuleLoadResult loadModule(SourceLocation ImportLoc,
56                              ModuleIdPath Path,
57                              Module::NameVisibilityKind Visibility,
58                              bool IsInclusionDirective) override {
59    return ModuleLoadResult();
60  }
61
62  void makeModuleVisible(Module *Mod,
63                         Module::NameVisibilityKind Visibility,
64                         SourceLocation ImportLoc,
65                         bool Complain) override { }
66
67  GlobalModuleIndex *loadGlobalModuleIndex(SourceLocation TriggerLoc) override
68    { return nullptr; }
69  bool lookupMissingImports(StringRef Name, SourceLocation TriggerLoc) override
70    { return 0; };
71};
72
73TEST_F(PPConditionalDirectiveRecordTest, PPRecAPI) {
74  const char *source =
75      "0 1\n"
76      "#if 1\n"
77      "2\n"
78      "#ifndef BB\n"
79      "3 4\n"
80      "#else\n"
81      "#endif\n"
82      "5\n"
83      "#endif\n"
84      "6\n"
85      "#if 1\n"
86      "7\n"
87      "#if 1\n"
88      "#endif\n"
89      "8\n"
90      "#endif\n"
91      "9\n";
92
93  MemoryBuffer *buf = MemoryBuffer::getMemBuffer(source);
94  SourceMgr.setMainFileID(SourceMgr.createFileID(buf));
95
96  VoidModuleLoader ModLoader;
97  HeaderSearch HeaderInfo(new HeaderSearchOptions, SourceMgr, Diags, LangOpts,
98                          Target.get());
99  Preprocessor PP(new PreprocessorOptions(), Diags, LangOpts, SourceMgr,
100                  HeaderInfo, ModLoader,
101                  /*IILookup =*/nullptr,
102                  /*OwnsHeaderSearch =*/false);
103  PP.Initialize(*Target);
104  PPConditionalDirectiveRecord *
105    PPRec = new PPConditionalDirectiveRecord(SourceMgr);
106  PP.addPPCallbacks(PPRec);
107  PP.EnterMainSourceFile();
108
109  std::vector<Token> toks;
110  while (1) {
111    Token tok;
112    PP.Lex(tok);
113    if (tok.is(tok::eof))
114      break;
115    toks.push_back(tok);
116  }
117
118  // Make sure we got the tokens that we expected.
119  ASSERT_EQ(10U, toks.size());
120
121  EXPECT_FALSE(PPRec->rangeIntersectsConditionalDirective(
122                    SourceRange(toks[0].getLocation(), toks[1].getLocation())));
123  EXPECT_TRUE(PPRec->rangeIntersectsConditionalDirective(
124                    SourceRange(toks[0].getLocation(), toks[2].getLocation())));
125  EXPECT_FALSE(PPRec->rangeIntersectsConditionalDirective(
126                    SourceRange(toks[3].getLocation(), toks[4].getLocation())));
127  EXPECT_TRUE(PPRec->rangeIntersectsConditionalDirective(
128                    SourceRange(toks[1].getLocation(), toks[5].getLocation())));
129  EXPECT_TRUE(PPRec->rangeIntersectsConditionalDirective(
130                    SourceRange(toks[2].getLocation(), toks[6].getLocation())));
131  EXPECT_FALSE(PPRec->rangeIntersectsConditionalDirective(
132                    SourceRange(toks[2].getLocation(), toks[5].getLocation())));
133  EXPECT_FALSE(PPRec->rangeIntersectsConditionalDirective(
134                    SourceRange(toks[0].getLocation(), toks[6].getLocation())));
135  EXPECT_TRUE(PPRec->rangeIntersectsConditionalDirective(
136                    SourceRange(toks[2].getLocation(), toks[8].getLocation())));
137  EXPECT_FALSE(PPRec->rangeIntersectsConditionalDirective(
138                    SourceRange(toks[0].getLocation(), toks[9].getLocation())));
139
140  EXPECT_TRUE(PPRec->areInDifferentConditionalDirectiveRegion(
141                    toks[0].getLocation(), toks[2].getLocation()));
142  EXPECT_FALSE(PPRec->areInDifferentConditionalDirectiveRegion(
143                    toks[3].getLocation(), toks[4].getLocation()));
144  EXPECT_TRUE(PPRec->areInDifferentConditionalDirectiveRegion(
145                    toks[1].getLocation(), toks[5].getLocation()));
146  EXPECT_TRUE(PPRec->areInDifferentConditionalDirectiveRegion(
147                    toks[2].getLocation(), toks[0].getLocation()));
148  EXPECT_FALSE(PPRec->areInDifferentConditionalDirectiveRegion(
149                    toks[4].getLocation(), toks[3].getLocation()));
150  EXPECT_TRUE(PPRec->areInDifferentConditionalDirectiveRegion(
151                    toks[5].getLocation(), toks[1].getLocation()));
152}
153
154} // anonymous namespace
155