1 //====-- unittests/Frontend/ReparseWorkingDirTest.cpp - FrontendAction tests =//
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-exception
7 //===----------------------------------------------------------------------===//
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"
23 using namespace clang
;
26 class ReparseWorkingDirTest
: public ::testing::Test
{
27 IntrusiveRefCntPtr
<vfs::InMemoryFileSystem
> VFS
;
28 std::shared_ptr
<PCHContainerOperations
> PCHContainerOpts
;
31 void SetUp() override
{ VFS
= new vfs::InMemoryFileSystem(); }
32 void TearDown() override
{}
34 void setWorkingDirectory(StringRef Path
) {
35 VFS
->setCurrentWorkingDirectory(Path
);
38 void AddFile(const std::string
&Filename
, const std::string
&Contents
) {
41 VFS
->addFile(Filename
, now
,
42 MemoryBuffer::getMemBufferCopy(Contents
, Filename
));
45 std::unique_ptr
<ASTUnit
> ParseAST(StringRef EntryFile
) {
46 PCHContainerOpts
= std::make_shared
<PCHContainerOperations
>();
47 auto CI
= std::make_shared
<CompilerInvocation
>();
48 CI
->getFrontendOpts().Inputs
.push_back(FrontendInputFile(
49 EntryFile
, FrontendOptions::getInputKindForExtension(
50 llvm::sys::path::extension(EntryFile
).substr(1))));
52 CI
->getHeaderSearchOpts().AddPath("headers",
53 frontend::IncludeDirGroup::Quoted
,
54 /*isFramework*/ false,
55 /*IgnoreSysRoot*/ false);
57 CI
->getFileSystemOpts().WorkingDir
= *VFS
->getCurrentWorkingDirectory();
58 CI
->getTargetOpts().Triple
= "i386-unknown-linux-gnu";
60 IntrusiveRefCntPtr
<DiagnosticsEngine
> Diags(
61 CompilerInstance::createDiagnostics(new DiagnosticOptions
,
62 new DiagnosticConsumer
));
64 FileManager
*FileMgr
= new FileManager(CI
->getFileSystemOpts(), VFS
);
66 std::unique_ptr
<ASTUnit
> AST
= ASTUnit::LoadFromCompilerInvocation(
67 CI
, PCHContainerOpts
, Diags
, FileMgr
, false, CaptureDiagsKind::None
,
68 /*PrecompilePreambleAfterNParses=*/1);
72 bool ReparseAST(const std::unique_ptr
<ASTUnit
> &AST
) {
74 AST
->Reparse(PCHContainerOpts
, /*RemappedFiles*/ {}, VFS
);
75 return !reparseFailed
;
79 TEST_F(ReparseWorkingDirTest
, ReparseWorkingDir
) {
80 // Setup the working directory path.
81 SmallString
<16> WorkingDir
;
87 llvm::sys::path::append(WorkingDir
, "root");
88 setWorkingDirectory(WorkingDir
);
90 SmallString
<32> Header
;
91 llvm::sys::path::append(Header
, WorkingDir
, "headers", "header.h");
93 SmallString
<32> MainName
;
94 llvm::sys::path::append(MainName
, WorkingDir
, "main.cpp");
96 AddFile(MainName
.str().str(), R
"cpp(
98 int main() { return foo(); }
100 AddFile(Header
.str().str(), R
"h(
101 static int foo() { return 0; }
104 // Parse the main file, ensuring we can include the header.
105 std::unique_ptr
<ASTUnit
> AST(ParseAST(MainName
.str()));
106 ASSERT_TRUE(AST
.get());
107 ASSERT_FALSE(AST
->getDiagnostics().hasErrorOccurred());
109 // Reparse and check that the working directory was preserved.
110 ASSERT_TRUE(ReparseAST(AST
));
112 const auto &FM
= AST
->getFileManager();
113 const auto &FS
= FM
.getVirtualFileSystem();
114 ASSERT_EQ(FM
.getFileSystemOpts().WorkingDir
, WorkingDir
);
115 ASSERT_EQ(*FS
.getCurrentWorkingDirectory(), WorkingDir
);
118 } // end anonymous namespace