124 lines · cpp
1//====-- unittests/Frontend/ReparseWorkingDirTest.cpp - FrontendAction 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/Basic/Diagnostic.h"10#include "clang/Basic/FileManager.h"11#include "clang/Frontend/ASTUnit.h"12#include "clang/Frontend/CompilerInstance.h"13#include "clang/Frontend/CompilerInvocation.h"14#include "clang/Frontend/FrontendActions.h"15#include "clang/Frontend/FrontendOptions.h"16#include "clang/Lex/PreprocessorOptions.h"17#include "llvm/Support/FileSystem.h"18#include "llvm/Support/MemoryBuffer.h"19#include "llvm/Support/Path.h"20#include "gtest/gtest.h"21 22using namespace llvm;23using namespace clang;24 25namespace {26class ReparseWorkingDirTest : public ::testing::Test {27 IntrusiveRefCntPtr<vfs::InMemoryFileSystem> VFS;28 std::shared_ptr<PCHContainerOperations> PCHContainerOpts;29 30public:31 void SetUp() override {32 VFS = llvm::makeIntrusiveRefCnt<vfs::InMemoryFileSystem>();33 }34 void TearDown() override {}35 36 void setWorkingDirectory(StringRef Path) {37 VFS->setCurrentWorkingDirectory(Path);38 }39 40 void AddFile(const std::string &Filename, const std::string &Contents) {41 ::time_t now;42 ::time(&now);43 VFS->addFile(Filename, now,44 MemoryBuffer::getMemBufferCopy(Contents, Filename));45 }46 47 std::unique_ptr<ASTUnit> ParseAST(StringRef EntryFile) {48 PCHContainerOpts = std::make_shared<PCHContainerOperations>();49 auto CI = std::make_shared<CompilerInvocation>();50 CI->getFrontendOpts().Inputs.push_back(FrontendInputFile(51 EntryFile, FrontendOptions::getInputKindForExtension(52 llvm::sys::path::extension(EntryFile).substr(1))));53 54 CI->getHeaderSearchOpts().AddPath("headers",55 frontend::IncludeDirGroup::Quoted,56 /*isFramework*/ false,57 /*IgnoreSysRoot*/ false);58 59 CI->getFileSystemOpts().WorkingDir = *VFS->getCurrentWorkingDirectory();60 CI->getTargetOpts().Triple = "i386-unknown-linux-gnu";61 62 auto DiagOpts = std::make_shared<DiagnosticOptions>();63 IntrusiveRefCntPtr<DiagnosticsEngine> Diags(64 CompilerInstance::createDiagnostics(*VFS, *DiagOpts,65 new DiagnosticConsumer));66 67 auto FileMgr =68 llvm::makeIntrusiveRefCnt<FileManager>(CI->getFileSystemOpts(), VFS);69 70 std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromCompilerInvocation(71 CI, PCHContainerOpts, DiagOpts, Diags, FileMgr, false,72 CaptureDiagsKind::None,73 /*PrecompilePreambleAfterNParses=*/1);74 return AST;75 }76 77 bool ReparseAST(const std::unique_ptr<ASTUnit> &AST) {78 bool reparseFailed =79 AST->Reparse(PCHContainerOpts, /*RemappedFiles*/ {}, VFS);80 return !reparseFailed;81 }82};83 84TEST_F(ReparseWorkingDirTest, ReparseWorkingDir) {85 // Setup the working directory path.86 SmallString<16> WorkingDir;87#ifdef _WIN3288 WorkingDir = "C:\\";89#else90 WorkingDir = "/";91#endif92 llvm::sys::path::append(WorkingDir, "root");93 setWorkingDirectory(WorkingDir);94 95 SmallString<32> Header;96 llvm::sys::path::append(Header, WorkingDir, "headers", "header.h");97 98 SmallString<32> MainName;99 llvm::sys::path::append(MainName, WorkingDir, "main.cpp");100 101 AddFile(MainName.str().str(), R"cpp(102#include "header.h"103int main() { return foo(); }104)cpp");105 AddFile(Header.str().str(), R"h(106static int foo() { return 0; }107)h");108 109 // Parse the main file, ensuring we can include the header.110 std::unique_ptr<ASTUnit> AST(ParseAST(MainName.str()));111 ASSERT_TRUE(AST.get());112 ASSERT_FALSE(AST->getDiagnostics().hasErrorOccurred());113 114 // Reparse and check that the working directory was preserved.115 ASSERT_TRUE(ReparseAST(AST));116 117 const auto &FM = AST->getFileManager();118 const auto &FS = FM.getVirtualFileSystem();119 ASSERT_EQ(FM.getFileSystemOpts().WorkingDir, WorkingDir);120 ASSERT_EQ(*FS.getCurrentWorkingDirectory(), WorkingDir);121}122 123} // end anonymous namespace124