593 lines · cpp
1//===- unittests/Lex/PPCallbacksTest.cpp - PPCallbacks tests ------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===--------------------------------------------------------------===//8 9#include "clang/Lex/Preprocessor.h"10#include "clang/AST/ASTConsumer.h"11#include "clang/AST/ASTContext.h"12#include "clang/Basic/Diagnostic.h"13#include "clang/Basic/DiagnosticOptions.h"14#include "clang/Basic/FileManager.h"15#include "clang/Basic/LangOptions.h"16#include "clang/Basic/SourceManager.h"17#include "clang/Basic/TargetInfo.h"18#include "clang/Basic/TargetOptions.h"19#include "clang/Lex/HeaderSearch.h"20#include "clang/Lex/HeaderSearchOptions.h"21#include "clang/Lex/ModuleLoader.h"22#include "clang/Lex/PreprocessorOptions.h"23#include "clang/Parse/Parser.h"24#include "clang/Sema/Sema.h"25#include "llvm/ADT/SmallString.h"26#include "llvm/Support/Path.h"27#include "gtest/gtest.h"28 29using namespace clang;30 31namespace {32 33// Stub to collect data from InclusionDirective callbacks.34class InclusionDirectiveCallbacks : public PPCallbacks {35public:36 void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok,37 StringRef FileName, bool IsAngled,38 CharSourceRange FilenameRange,39 OptionalFileEntryRef File, StringRef SearchPath,40 StringRef RelativePath, const Module *SuggestedModule,41 bool ModuleImported,42 SrcMgr::CharacteristicKind FileType) override {43 this->HashLoc = HashLoc;44 this->IncludeTok = IncludeTok;45 this->FileName = FileName.str();46 this->IsAngled = IsAngled;47 this->FilenameRange = FilenameRange;48 this->File = File;49 this->SearchPath = SearchPath.str();50 this->RelativePath = RelativePath.str();51 this->SuggestedModule = SuggestedModule;52 this->ModuleImported = ModuleImported;53 this->FileType = FileType;54 }55 56 SourceLocation HashLoc;57 Token IncludeTok;58 SmallString<16> FileName;59 bool IsAngled;60 CharSourceRange FilenameRange;61 OptionalFileEntryRef File;62 SmallString<16> SearchPath;63 SmallString<16> RelativePath;64 const Module *SuggestedModule;65 bool ModuleImported;66 SrcMgr::CharacteristicKind FileType;67};68 69class CondDirectiveCallbacks : public PPCallbacks {70public:71 struct Result {72 SourceRange ConditionRange;73 ConditionValueKind ConditionValue;74 75 Result(SourceRange R, ConditionValueKind K)76 : ConditionRange(R), ConditionValue(K) {}77 };78 79 std::vector<Result> Results;80 81 void If(SourceLocation Loc, SourceRange ConditionRange,82 ConditionValueKind ConditionValue) override {83 Results.emplace_back(ConditionRange, ConditionValue);84 }85 86 void Elif(SourceLocation Loc, SourceRange ConditionRange,87 ConditionValueKind ConditionValue, SourceLocation IfLoc) override {88 Results.emplace_back(ConditionRange, ConditionValue);89 }90};91 92// Stub to collect data from PragmaOpenCLExtension callbacks.93class PragmaOpenCLExtensionCallbacks : public PPCallbacks {94public:95 typedef struct {96 SmallString<16> Name;97 unsigned State;98 } CallbackParameters;99 100 PragmaOpenCLExtensionCallbacks() : Name("Not called."), State(99) {}101 102 void PragmaOpenCLExtension(clang::SourceLocation NameLoc,103 const clang::IdentifierInfo *Name,104 clang::SourceLocation StateLoc,105 unsigned State) override {106 this->NameLoc = NameLoc;107 this->Name = Name->getName();108 this->StateLoc = StateLoc;109 this->State = State;110 }111 112 SourceLocation NameLoc;113 SmallString<16> Name;114 SourceLocation StateLoc;115 unsigned State;116};117 118class PragmaMarkCallbacks : public PPCallbacks {119public:120 struct Mark {121 SourceLocation Location;122 std::string Trivia;123 };124 125 std::vector<Mark> Marks;126 127 void PragmaMark(SourceLocation Loc, StringRef Trivia) override {128 Marks.emplace_back(Mark{Loc, Trivia.str()});129 }130};131 132// PPCallbacks test fixture.133class PPCallbacksTest : public ::testing::Test {134protected:135 PPCallbacksTest()136 : InMemoryFileSystem(137 llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>()),138 FileMgr(FileSystemOptions(), InMemoryFileSystem),139 DiagID(DiagnosticIDs::create()),140 Diags(DiagID, DiagOpts, new IgnoringDiagConsumer()),141 SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions()) {142 TargetOpts->Triple = "x86_64-apple-darwin11.1.0";143 Target = TargetInfo::CreateTargetInfo(Diags, *TargetOpts);144 }145 146 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem;147 FileManager FileMgr;148 IntrusiveRefCntPtr<DiagnosticIDs> DiagID;149 DiagnosticOptions DiagOpts;150 DiagnosticsEngine Diags;151 SourceManager SourceMgr;152 LangOptions LangOpts;153 std::shared_ptr<TargetOptions> TargetOpts;154 IntrusiveRefCntPtr<TargetInfo> Target;155 156 // Register a header path as a known file and add its location157 // to search path.158 void AddFakeHeader(HeaderSearch &HeaderInfo, const char *HeaderPath,159 bool IsSystemHeader) {160 // Tell FileMgr about header.161 InMemoryFileSystem->addFile(HeaderPath, 0,162 llvm::MemoryBuffer::getMemBuffer("\n"));163 164 // Add header's parent path to search path.165 StringRef SearchPath = llvm::sys::path::parent_path(HeaderPath);166 auto DE = FileMgr.getOptionalDirectoryRef(SearchPath);167 DirectoryLookup DL(*DE, SrcMgr::C_User, false);168 HeaderInfo.AddSearchPath(DL, IsSystemHeader);169 }170 171 // Get the raw source string of the range.172 StringRef GetSourceString(CharSourceRange Range) {173 const char* B = SourceMgr.getCharacterData(Range.getBegin());174 const char* E = SourceMgr.getCharacterData(Range.getEnd());175 176 return StringRef(B, E - B);177 }178 179 StringRef GetSourceStringToEnd(CharSourceRange Range) {180 const char *B = SourceMgr.getCharacterData(Range.getBegin());181 const char *E = SourceMgr.getCharacterData(Range.getEnd());182 183 return StringRef(184 B,185 E - B + Lexer::MeasureTokenLength(Range.getEnd(), SourceMgr, LangOpts));186 }187 188 // Run lexer over SourceText and collect FilenameRange from189 // the InclusionDirective callback.190 CharSourceRange InclusionDirectiveFilenameRange(const char *SourceText,191 const char *HeaderPath,192 bool SystemHeader) {193 std::unique_ptr<llvm::MemoryBuffer> Buf =194 llvm::MemoryBuffer::getMemBuffer(SourceText);195 SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf)));196 197 HeaderSearchOptions HSOpts;198 TrivialModuleLoader ModLoader;199 200 HeaderSearch HeaderInfo(HSOpts, SourceMgr, Diags, LangOpts, Target.get());201 AddFakeHeader(HeaderInfo, HeaderPath, SystemHeader);202 203 PreprocessorOptions PPOpts;204 Preprocessor PP(PPOpts, Diags, LangOpts, SourceMgr, HeaderInfo, ModLoader,205 /*IILookup=*/nullptr, /*OwnsHeaderSearch=*/false);206 return InclusionDirectiveCallback(PP)->FilenameRange;207 }208 209 SrcMgr::CharacteristicKind InclusionDirectiveCharacteristicKind(210 const char *SourceText, const char *HeaderPath, bool SystemHeader) {211 std::unique_ptr<llvm::MemoryBuffer> Buf =212 llvm::MemoryBuffer::getMemBuffer(SourceText);213 SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf)));214 215 HeaderSearchOptions HSOpts;216 TrivialModuleLoader ModLoader;217 218 HeaderSearch HeaderInfo(HSOpts, SourceMgr, Diags, LangOpts, Target.get());219 AddFakeHeader(HeaderInfo, HeaderPath, SystemHeader);220 221 PreprocessorOptions PPOpts;222 Preprocessor PP(PPOpts, Diags, LangOpts, SourceMgr, HeaderInfo, ModLoader,223 /*IILookup=*/nullptr, /*OwnsHeaderSearch=*/false);224 return InclusionDirectiveCallback(PP)->FileType;225 }226 227 InclusionDirectiveCallbacks *InclusionDirectiveCallback(Preprocessor &PP) {228 PP.Initialize(*Target);229 InclusionDirectiveCallbacks* Callbacks = new InclusionDirectiveCallbacks;230 PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Callbacks));231 232 // Lex source text.233 PP.EnterMainSourceFile();234 PP.LexTokensUntilEOF();235 236 // Callbacks have been executed at this point -- return filename range.237 return Callbacks;238 }239 240 std::vector<CondDirectiveCallbacks::Result>241 DirectiveExprRange(StringRef SourceText, PreprocessorOptions PPOpts = {}) {242 HeaderSearchOptions HSOpts;243 TrivialModuleLoader ModLoader;244 std::unique_ptr<llvm::MemoryBuffer> Buf =245 llvm::MemoryBuffer::getMemBuffer(SourceText);246 SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(Buf)));247 HeaderSearch HeaderInfo(HSOpts, SourceMgr, Diags, LangOpts, Target.get());248 Preprocessor PP(PPOpts, Diags, LangOpts, SourceMgr, HeaderInfo, ModLoader,249 /*IILookup=*/nullptr, /*OwnsHeaderSearch=*/false);250 PP.Initialize(*Target);251 auto *Callbacks = new CondDirectiveCallbacks;252 PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Callbacks));253 254 // Lex source text.255 PP.EnterMainSourceFile();256 PP.LexTokensUntilEOF();257 258 return Callbacks->Results;259 }260 261 std::vector<PragmaMarkCallbacks::Mark>262 PragmaMarkCall(const char *SourceText) {263 std::unique_ptr<llvm::MemoryBuffer> SourceBuf =264 llvm::MemoryBuffer::getMemBuffer(SourceText, "test.c");265 SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(SourceBuf)));266 267 HeaderSearchOptions HSOpts;268 TrivialModuleLoader ModLoader;269 PreprocessorOptions PPOpts;270 271 HeaderSearch HeaderInfo(HSOpts, SourceMgr, Diags, LangOpts, Target.get());272 273 Preprocessor PP(PPOpts, Diags, LangOpts, SourceMgr, HeaderInfo, ModLoader,274 /*IILookup=*/nullptr, /*OwnsHeaderSearch=*/false);275 PP.Initialize(*Target);276 277 auto *Callbacks = new PragmaMarkCallbacks;278 PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Callbacks));279 280 // Lex source text.281 PP.EnterMainSourceFile();282 PP.LexTokensUntilEOF();283 284 return Callbacks->Marks;285 }286 287 PragmaOpenCLExtensionCallbacks::CallbackParameters288 PragmaOpenCLExtensionCall(const char *SourceText) {289 LangOptions OpenCLLangOpts;290 OpenCLLangOpts.OpenCL = 1;291 292 std::unique_ptr<llvm::MemoryBuffer> SourceBuf =293 llvm::MemoryBuffer::getMemBuffer(SourceText, "test.cl");294 SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(SourceBuf)));295 296 HeaderSearchOptions HSOpts;297 TrivialModuleLoader ModLoader;298 PreprocessorOptions PPOpts;299 300 HeaderSearch HeaderInfo(HSOpts, SourceMgr, Diags, OpenCLLangOpts,301 Target.get());302 303 Preprocessor PP(PPOpts, Diags, OpenCLLangOpts, SourceMgr, HeaderInfo,304 ModLoader, /*IILookup=*/nullptr,305 /*OwnsHeaderSearch=*/false);306 PP.Initialize(*Target);307 308 // parser actually sets correct pragma handlers for preprocessor309 // according to LangOptions, so we init Parser to register opencl310 // pragma handlers311 ASTContext Context(OpenCLLangOpts, SourceMgr, PP.getIdentifierTable(),312 PP.getSelectorTable(), PP.getBuiltinInfo(), PP.TUKind);313 Context.InitBuiltinTypes(*Target);314 315 ASTConsumer Consumer;316 Sema S(PP, Context, Consumer);317 Parser P(PP, S, false);318 PragmaOpenCLExtensionCallbacks* Callbacks = new PragmaOpenCLExtensionCallbacks;319 PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Callbacks));320 321 // Lex source text.322 PP.EnterMainSourceFile();323 PP.LexTokensUntilEOF();324 325 PragmaOpenCLExtensionCallbacks::CallbackParameters RetVal = {326 Callbacks->Name,327 Callbacks->State328 };329 return RetVal;330 }331};332 333TEST_F(PPCallbacksTest, UserFileCharacteristics) {334 const char *Source = "#include \"quoted.h\"\n";335 336 SrcMgr::CharacteristicKind Kind =337 InclusionDirectiveCharacteristicKind(Source, "/quoted.h", false);338 339 ASSERT_EQ(SrcMgr::CharacteristicKind::C_User, Kind);340}341 342TEST_F(PPCallbacksTest, QuotedFilename) {343 const char* Source =344 "#include \"quoted.h\"\n";345 346 CharSourceRange Range =347 InclusionDirectiveFilenameRange(Source, "/quoted.h", false);348 349 ASSERT_EQ("\"quoted.h\"", GetSourceString(Range));350}351 352TEST_F(PPCallbacksTest, AngledFilename) {353 const char* Source =354 "#include <angled.h>\n";355 356 CharSourceRange Range =357 InclusionDirectiveFilenameRange(Source, "/angled.h", true);358 359 ASSERT_EQ("<angled.h>", GetSourceString(Range));360}361 362TEST_F(PPCallbacksTest, QuotedInMacro) {363 const char* Source =364 "#define MACRO_QUOTED \"quoted.h\"\n"365 "#include MACRO_QUOTED\n";366 367 CharSourceRange Range =368 InclusionDirectiveFilenameRange(Source, "/quoted.h", false);369 370 ASSERT_EQ("\"quoted.h\"", GetSourceString(Range));371}372 373TEST_F(PPCallbacksTest, AngledInMacro) {374 const char* Source =375 "#define MACRO_ANGLED <angled.h>\n"376 "#include MACRO_ANGLED\n";377 378 CharSourceRange Range =379 InclusionDirectiveFilenameRange(Source, "/angled.h", true);380 381 ASSERT_EQ("<angled.h>", GetSourceString(Range));382}383 384TEST_F(PPCallbacksTest, StringizedMacroArgument) {385 const char* Source =386 "#define MACRO_STRINGIZED(x) #x\n"387 "#include MACRO_STRINGIZED(quoted.h)\n";388 389 CharSourceRange Range =390 InclusionDirectiveFilenameRange(Source, "/quoted.h", false);391 392 ASSERT_EQ("\"quoted.h\"", GetSourceString(Range));393}394 395TEST_F(PPCallbacksTest, ConcatenatedMacroArgument) {396 const char* Source =397 "#define MACRO_ANGLED <angled.h>\n"398 "#define MACRO_CONCAT(x, y) x ## _ ## y\n"399 "#include MACRO_CONCAT(MACRO, ANGLED)\n";400 401 CharSourceRange Range =402 InclusionDirectiveFilenameRange(Source, "/angled.h", false);403 404 ASSERT_EQ("<angled.h>", GetSourceString(Range));405}406 407TEST_F(PPCallbacksTest, TrigraphFilename) {408 const char* Source =409 "#include \"tri\?\?-graph.h\"\n";410 411 CharSourceRange Range =412 InclusionDirectiveFilenameRange(Source, "/tri~graph.h", false);413 414 ASSERT_EQ("\"tri\?\?-graph.h\"", GetSourceString(Range));415}416 417TEST_F(PPCallbacksTest, TrigraphInMacro) {418 const char* Source =419 "#define MACRO_TRIGRAPH \"tri\?\?-graph.h\"\n"420 "#include MACRO_TRIGRAPH\n";421 422 CharSourceRange Range =423 InclusionDirectiveFilenameRange(Source, "/tri~graph.h", false);424 425 ASSERT_EQ("\"tri\?\?-graph.h\"", GetSourceString(Range));426}427 428TEST_F(PPCallbacksTest, FileNotFoundSkipped) {429 const char *SourceText = "#include \"skipped.h\"\n";430 431 std::unique_ptr<llvm::MemoryBuffer> SourceBuf =432 llvm::MemoryBuffer::getMemBuffer(SourceText);433 SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(SourceBuf)));434 435 HeaderSearchOptions HSOpts;436 TrivialModuleLoader ModLoader;437 PreprocessorOptions PPOpts;438 HeaderSearch HeaderInfo(HSOpts, SourceMgr, Diags, LangOpts, Target.get());439 440 DiagnosticConsumer *DiagConsumer = new DiagnosticConsumer;441 DiagnosticsEngine FileNotFoundDiags(DiagID, DiagOpts, DiagConsumer);442 Preprocessor PP(PPOpts, FileNotFoundDiags, LangOpts, SourceMgr, HeaderInfo,443 ModLoader, /*IILookup=*/nullptr, /*OwnsHeaderSearch=*/false);444 PP.Initialize(*Target);445 446 class FileNotFoundCallbacks : public PPCallbacks {447 public:448 unsigned int NumCalls = 0;449 bool FileNotFound(StringRef FileName) override {450 NumCalls++;451 return FileName == "skipped.h";452 }453 };454 455 auto *Callbacks = new FileNotFoundCallbacks;456 PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(Callbacks));457 458 // Lex source text.459 PP.EnterMainSourceFile();460 PP.LexTokensUntilEOF();461 462 ASSERT_EQ(1u, Callbacks->NumCalls);463 ASSERT_EQ(0u, DiagConsumer->getNumErrors());464}465 466TEST_F(PPCallbacksTest, OpenCLExtensionPragmaEnabled) {467 const char* Source =468 "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n";469 470 PragmaOpenCLExtensionCallbacks::CallbackParameters Parameters =471 PragmaOpenCLExtensionCall(Source);472 473 ASSERT_EQ("cl_khr_fp64", Parameters.Name);474 unsigned ExpectedState = 1;475 ASSERT_EQ(ExpectedState, Parameters.State);476}477 478TEST_F(PPCallbacksTest, OpenCLExtensionPragmaDisabled) {479 const char* Source =480 "#pragma OPENCL EXTENSION cl_khr_fp16 : disable\n";481 482 PragmaOpenCLExtensionCallbacks::CallbackParameters Parameters =483 PragmaOpenCLExtensionCall(Source);484 485 ASSERT_EQ("cl_khr_fp16", Parameters.Name);486 unsigned ExpectedState = 0;487 ASSERT_EQ(ExpectedState, Parameters.State);488}489 490TEST_F(PPCallbacksTest, CollectMarks) {491 const char *Source =492 "#pragma mark\n"493 "#pragma mark\r\n"494 "#pragma mark - trivia\n"495 "#pragma mark - trivia\r\n";496 497 auto Marks = PragmaMarkCall(Source);498 499 ASSERT_EQ(4u, Marks.size());500 ASSERT_TRUE(Marks[0].Trivia.empty());501 ASSERT_TRUE(Marks[1].Trivia.empty());502 ASSERT_FALSE(Marks[2].Trivia.empty());503 ASSERT_FALSE(Marks[3].Trivia.empty());504 ASSERT_EQ(" - trivia", Marks[2].Trivia);505 ASSERT_EQ(" - trivia", Marks[3].Trivia);506}507 508TEST_F(PPCallbacksTest, DirectiveExprRanges) {509 const auto &Results1 = DirectiveExprRange("#if FLUZZY_FLOOF\n#endif\n");510 EXPECT_EQ(Results1.size(), 1U);511 EXPECT_EQ(512 GetSourceStringToEnd(CharSourceRange(Results1[0].ConditionRange, false)),513 "FLUZZY_FLOOF");514 515 const auto &Results2 = DirectiveExprRange("#if 1 + 4 < 7\n#endif\n");516 EXPECT_EQ(Results2.size(), 1U);517 EXPECT_EQ(518 GetSourceStringToEnd(CharSourceRange(Results2[0].ConditionRange, false)),519 "1 + 4 < 7");520 521 const auto &Results3 = DirectiveExprRange("#if 1 + \\\n 2\n#endif\n");522 EXPECT_EQ(Results3.size(), 1U);523 EXPECT_EQ(524 GetSourceStringToEnd(CharSourceRange(Results3[0].ConditionRange, false)),525 "1 + \\\n 2");526 527 const auto &Results4 = DirectiveExprRange("#if 0\n#elif FLOOFY\n#endif\n");528 EXPECT_EQ(Results4.size(), 2U);529 EXPECT_EQ(530 GetSourceStringToEnd(CharSourceRange(Results4[0].ConditionRange, false)),531 "0");532 EXPECT_EQ(533 GetSourceStringToEnd(CharSourceRange(Results4[1].ConditionRange, false)),534 "FLOOFY");535 536 const auto &Results5 = DirectiveExprRange("#if 1\n#elif FLOOFY\n#endif\n");537 EXPECT_EQ(Results5.size(), 2U);538 EXPECT_EQ(539 GetSourceStringToEnd(CharSourceRange(Results5[0].ConditionRange, false)),540 "1");541 EXPECT_EQ(542 GetSourceStringToEnd(CharSourceRange(Results5[1].ConditionRange, false)),543 "FLOOFY");544 545 const auto &Results6 =546 DirectiveExprRange("#if defined(FLUZZY_FLOOF)\n#endif\n");547 EXPECT_EQ(Results6.size(), 1U);548 EXPECT_EQ(549 GetSourceStringToEnd(CharSourceRange(Results6[0].ConditionRange, false)),550 "defined(FLUZZY_FLOOF)");551 552 const auto &Results7 =553 DirectiveExprRange("#if 1\n#elif defined(FLOOFY)\n#endif\n");554 EXPECT_EQ(Results7.size(), 2U);555 EXPECT_EQ(556 GetSourceStringToEnd(CharSourceRange(Results7[0].ConditionRange, false)),557 "1");558 EXPECT_EQ(559 GetSourceStringToEnd(CharSourceRange(Results7[1].ConditionRange, false)),560 "defined(FLOOFY)");561 562 const auto &Results8 =563 DirectiveExprRange("#define FLOOFY 0\n#if __FILE__ > FLOOFY\n#endif\n");564 EXPECT_EQ(Results8.size(), 1U);565 EXPECT_EQ(566 GetSourceStringToEnd(CharSourceRange(Results8[0].ConditionRange, false)),567 "__FILE__ > FLOOFY");568 EXPECT_EQ(569 Lexer::getSourceText(CharSourceRange(Results8[0].ConditionRange, false),570 SourceMgr, LangOpts),571 "__FILE__ > FLOOFY");572 573 const char *MultiExprIf = "#if defined(FLOOFY) || defined(FLUZZY)\n#endif\n";574 const auto &Results9 = DirectiveExprRange(MultiExprIf);575 EXPECT_EQ(Results9.size(), 1U);576 EXPECT_EQ(577 Lexer::getSourceText(CharSourceRange(Results9[0].ConditionRange, false),578 SourceMgr, LangOpts),579 "defined(FLOOFY) || defined(FLUZZY)");580 581 PreprocessorOptions PPOptsSingleFileParse;582 PPOptsSingleFileParse.SingleFileParseMode = true;583 const auto &Results10 =584 DirectiveExprRange(MultiExprIf, PPOptsSingleFileParse);585 EXPECT_EQ(Results10.size(), 1U);586 EXPECT_EQ(587 Lexer::getSourceText(CharSourceRange(Results10[0].ConditionRange, false),588 SourceMgr, LangOpts),589 "defined(FLOOFY) || defined(FLUZZY)");590}591 592} // namespace593