brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.8 KiB · 15cc283 Raw
159 lines · cpp
1//===- unittests/Lex/PPDependencyDirectivesTest.cpp -------------------------=//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/Basic/Diagnostic.h"10#include "clang/Basic/DiagnosticOptions.h"11#include "clang/Basic/FileManager.h"12#include "clang/Basic/LangOptions.h"13#include "clang/Basic/SourceManager.h"14#include "clang/Basic/TargetInfo.h"15#include "clang/Basic/TargetOptions.h"16#include "clang/Lex/DependencyDirectivesScanner.h"17#include "clang/Lex/HeaderSearch.h"18#include "clang/Lex/HeaderSearchOptions.h"19#include "clang/Lex/ModuleLoader.h"20#include "clang/Lex/Preprocessor.h"21#include "clang/Lex/PreprocessorOptions.h"22#include "llvm/Testing/Support/Error.h"23#include "gtest/gtest.h"24#include <optional>25 26using namespace clang;27 28namespace {29 30// The test fixture.31class PPDependencyDirectivesTest : public ::testing::Test {32protected:33  PPDependencyDirectivesTest()34      : FileMgr(FileMgrOpts),35        Diags(DiagnosticIDs::create(), DiagOpts, new IgnoringDiagConsumer()),36        SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions) {37    TargetOpts->Triple = "x86_64-apple-macos12";38    Target = TargetInfo::CreateTargetInfo(Diags, *TargetOpts);39  }40 41  FileSystemOptions FileMgrOpts;42  FileManager FileMgr;43  DiagnosticOptions DiagOpts;44  DiagnosticsEngine Diags;45  SourceManager SourceMgr;46  LangOptions LangOpts;47  std::shared_ptr<TargetOptions> TargetOpts;48  IntrusiveRefCntPtr<TargetInfo> Target;49};50 51class IncludeCollector : public PPCallbacks {52public:53  Preprocessor &PP;54  SmallVectorImpl<StringRef> &IncludedFiles;55 56  IncludeCollector(Preprocessor &PP, SmallVectorImpl<StringRef> &IncludedFiles)57      : PP(PP), IncludedFiles(IncludedFiles) {}58 59  void LexedFileChanged(FileID FID, LexedFileChangeReason Reason,60                        SrcMgr::CharacteristicKind FileType, FileID PrevFID,61                        SourceLocation Loc) override {62    if (Reason != LexedFileChangeReason::EnterFile)63      return;64    if (FID == PP.getPredefinesFileID())65      return;66    StringRef Filename =67        PP.getSourceManager().getSLocEntry(FID).getFile().getName();68    IncludedFiles.push_back(Filename);69  }70};71 72TEST_F(PPDependencyDirectivesTest, MacroGuard) {73  // "head1.h" has a macro guard and should only be included once.74  // "head2.h" and "head3.h" have tokens following the macro check, they should75  // be included multiple times.76 77  auto VFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();78  VFS->addFile(79      "head1.h", 0,80      llvm::MemoryBuffer::getMemBuffer("#ifndef H1_H\n#define H1_H\n#endif\n"));81  VFS->addFile(82      "head2.h", 0,83      llvm::MemoryBuffer::getMemBuffer("#ifndef H2_H\n#define H2_H\n#endif\n\n"84                                       "extern int foo;\n"));85  VFS->addFile("head3.h", 0,86               llvm::MemoryBuffer::getMemBuffer(87                   "#ifndef H3_H\n#define H3_H\n#endif\n\n"88                   "#ifdef SOMEMAC\nextern int foo;\n#endif\n"));89  VFS->addFile("main.c", 0,90               llvm::MemoryBuffer::getMemBuffer(91                   "#include \"head1.h\"\n#include \"head1.h\"\n"92                   "#include \"head2.h\"\n#include \"head2.h\"\n"93                   "#include \"head3.h\"\n#include \"head3.h\"\n"));94  FileMgr.setVirtualFileSystem(VFS);95 96  OptionalFileEntryRef FE;97  ASSERT_THAT_ERROR(FileMgr.getFileRef("main.c").moveInto(FE),98                    llvm::Succeeded());99  SourceMgr.setMainFileID(100      SourceMgr.createFileID(*FE, SourceLocation(), SrcMgr::C_User));101 102  struct DepDirectives {103    SmallVector<dependency_directives_scan::Token> Tokens;104    SmallVector<dependency_directives_scan::Directive> Directives;105  };106 107  class TestDependencyDirectivesGetter : public DependencyDirectivesGetter {108    FileManager &FileMgr;109    SmallVector<std::unique_ptr<DepDirectives>> DepDirectivesObjects;110 111  public:112    TestDependencyDirectivesGetter(FileManager &FileMgr) : FileMgr(FileMgr) {}113 114    std::unique_ptr<DependencyDirectivesGetter>115    cloneFor(FileManager &FileMgr) override {116      return std::make_unique<TestDependencyDirectivesGetter>(FileMgr);117    }118 119    std::optional<ArrayRef<dependency_directives_scan::Directive>>120    operator()(FileEntryRef File) override {121      DepDirectivesObjects.push_back(std::make_unique<DepDirectives>());122      StringRef Input = (*FileMgr.getBufferForFile(File))->getBuffer();123      bool Err = scanSourceForDependencyDirectives(124          Input, DepDirectivesObjects.back()->Tokens,125          DepDirectivesObjects.back()->Directives);126      EXPECT_FALSE(Err);127      return DepDirectivesObjects.back()->Directives;128    }129  };130  TestDependencyDirectivesGetter GetDependencyDirectives(FileMgr);131 132  PreprocessorOptions PPOpts;133  HeaderSearchOptions HSOpts;134  TrivialModuleLoader ModLoader;135  HeaderSearch HeaderInfo(HSOpts, SourceMgr, Diags, LangOpts, Target.get());136  Preprocessor PP(PPOpts, Diags, LangOpts, SourceMgr, HeaderInfo, ModLoader,137                  /*IILookup =*/nullptr,138                  /*OwnsHeaderSearch =*/false);139  PP.Initialize(*Target);140 141  PP.setDependencyDirectivesGetter(GetDependencyDirectives);142 143  SmallVector<StringRef> IncludedFiles;144  PP.addPPCallbacks(std::make_unique<IncludeCollector>(PP, IncludedFiles));145  PP.EnterMainSourceFile();146  PP.LexTokensUntilEOF();147 148  SmallVector<std::string> IncludedFilesSlash;149  for (StringRef IncludedFile : IncludedFiles)150    IncludedFilesSlash.push_back(151        llvm::sys::path::convert_to_slash(IncludedFile));152  SmallVector<std::string> ExpectedIncludes{153      "main.c", "./head1.h", "./head2.h", "./head2.h", "./head3.h", "./head3.h",154  };155  EXPECT_EQ(IncludedFilesSlash, ExpectedIncludes);156}157 158} // anonymous namespace159