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