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-exception
6//
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 { VFS = new vfs::InMemoryFileSystem(); }
32 void TearDown() override {}
33
34 void setWorkingDirectory(StringRef Path) {
35 VFS->setCurrentWorkingDirectory(Path);
36 }
37
38 void AddFile(const std::string &Filename, const std::string &Contents) {
39 ::time_t now;
40 ::time(timer: &now);
41 VFS->addFile(Path: Filename, ModificationTime: now,
42 Buffer: MemoryBuffer::getMemBufferCopy(InputData: Contents, BufferName: Filename));
43 }
44
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(Elt: FrontendInputFile(
49 EntryFile, FrontendOptions::getInputKindForExtension(
50 Extension: llvm::sys::path::extension(path: EntryFile).substr(Start: 1))));
51
52 CI->getHeaderSearchOpts().AddPath(Path: "headers",
53 Group: frontend::IncludeDirGroup::Quoted,
54 /*isFramework*/ IsFramework: false,
55 /*IgnoreSysRoot*/ false);
56
57 CI->getFileSystemOpts().WorkingDir = *VFS->getCurrentWorkingDirectory();
58 CI->getTargetOpts().Triple = "i386-unknown-linux-gnu";
59
60 auto DiagOpts = std::make_shared<DiagnosticOptions>();
61 IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
62 CompilerInstance::createDiagnostics(VFS&: *VFS, Opts&: *DiagOpts,
63 Client: new DiagnosticConsumer));
64
65 FileManager *FileMgr = new FileManager(CI->getFileSystemOpts(), VFS);
66
67 std::unique_ptr<ASTUnit> AST = ASTUnit::LoadFromCompilerInvocation(
68 CI, PCHContainerOps: PCHContainerOpts, DiagOpts, Diags, FileMgr, OnlyLocalDecls: false,
69 CaptureDiagnostics: CaptureDiagsKind::None,
70 /*PrecompilePreambleAfterNParses=*/1);
71 return AST;
72 }
73
74 bool ReparseAST(const std::unique_ptr<ASTUnit> &AST) {
75 bool reparseFailed =
76 AST->Reparse(PCHContainerOps: PCHContainerOpts, /*RemappedFiles*/ {}, VFS);
77 return !reparseFailed;
78 }
79};
80
81TEST_F(ReparseWorkingDirTest, ReparseWorkingDir) {
82 // Setup the working directory path.
83 SmallString<16> WorkingDir;
84#ifdef _WIN32
85 WorkingDir = "C:\\";
86#else
87 WorkingDir = "/";
88#endif
89 llvm::sys::path::append(path&: WorkingDir, a: "root");
90 setWorkingDirectory(WorkingDir);
91
92 SmallString<32> Header;
93 llvm::sys::path::append(path&: Header, a: WorkingDir, b: "headers", c: "header.h");
94
95 SmallString<32> MainName;
96 llvm::sys::path::append(path&: MainName, a: WorkingDir, b: "main.cpp");
97
98 AddFile(Filename: MainName.str().str(), Contents: R"cpp(
99#include "header.h"
100int main() { return foo(); }
101)cpp");
102 AddFile(Filename: Header.str().str(), Contents: R"h(
103static int foo() { return 0; }
104)h");
105
106 // Parse the main file, ensuring we can include the header.
107 std::unique_ptr<ASTUnit> AST(ParseAST(EntryFile: MainName.str()));
108 ASSERT_TRUE(AST.get());
109 ASSERT_FALSE(AST->getDiagnostics().hasErrorOccurred());
110
111 // Reparse and check that the working directory was preserved.
112 ASSERT_TRUE(ReparseAST(AST));
113
114 const auto &FM = AST->getFileManager();
115 const auto &FS = FM.getVirtualFileSystem();
116 ASSERT_EQ(FM.getFileSystemOpts().WorkingDir, WorkingDir);
117 ASSERT_EQ(*FS.getCurrentWorkingDirectory(), WorkingDir);
118}
119
120} // end anonymous namespace
121

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of clang/unittests/Frontend/ReparseWorkingDirTest.cpp