CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
132 lines
4.3 KiB
C++
132 lines
4.3 KiB
C++
//===- unittests/Lex/ModuleMapTest.cpp - PPCallbacks tests ------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===--------------------------------------------------------------===//
|
|
//
|
|
|
|
#include "clang/Lex/ModuleMap.h"
|
|
#include "clang/Basic/SourceManager.h"
|
|
#include "clang/Basic/TargetInfo.h"
|
|
#include "clang/Basic/TargetOptions.h"
|
|
#include "clang/Lex/HeaderSearch.h"
|
|
#include "clang/Lex/HeaderSearchOptions.h"
|
|
#include "llvm/Support/Path.h"
|
|
#include "llvm/Support/VirtualFileSystem.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
#include <vector>
|
|
|
|
namespace clang {
|
|
namespace {
|
|
|
|
struct InterceptorFS : llvm::vfs::ProxyFileSystem {
|
|
// Record the paths looked up by a ModuleMap.
|
|
std::vector<std::string> StatPaths;
|
|
|
|
InterceptorFS(IntrusiveRefCntPtr<llvm::vfs::FileSystem> UnderlyingFS)
|
|
: ProxyFileSystem(UnderlyingFS) {}
|
|
|
|
llvm::ErrorOr<llvm::vfs::Status> status(const Twine &Path) override {
|
|
StatPaths.emplace_back(Path.str());
|
|
return ProxyFileSystem::status(Path);
|
|
}
|
|
};
|
|
|
|
class ModuleMapTest : public ::testing::Test {
|
|
protected:
|
|
ModuleMapTest()
|
|
: InMemFS(llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>()),
|
|
VFS(llvm::makeIntrusiveRefCnt<InterceptorFS>(InMemFS)),
|
|
FileMgr(FileMgrOpts, VFS),
|
|
Diagnostics(DiagnosticIDs::create(), DiagnosticOpts,
|
|
new IgnoringDiagConsumer()),
|
|
SrcMgr(Diagnostics, FileMgr), TargetOpts(new TargetOptions),
|
|
HdrSearch(HdrSearchOpts, SrcMgr, Diagnostics, LangOpts,
|
|
/* Target = */ nullptr),
|
|
Map(SrcMgr, Diagnostics, LangOpts, /* Target= */ nullptr, HdrSearch) {
|
|
TargetOpts->Triple = "x86_64-apple-darwin11.1.0";
|
|
Target = TargetInfo::CreateTargetInfo(Diagnostics, *TargetOpts);
|
|
Map.setTarget(*Target);
|
|
}
|
|
|
|
void addFile(llvm::StringRef Path, llvm::StringRef Content) {
|
|
InMemFS->addFile(Path, 0, llvm::MemoryBuffer::getMemBufferCopy(Content));
|
|
}
|
|
|
|
bool loadRoot(llvm::StringRef Path) {
|
|
auto File = FileMgr.getOptionalFileRef(Path);
|
|
if (!File) {
|
|
// parseAndLoadModuleMapFile returns false on success, true on error.
|
|
return true;
|
|
}
|
|
return Map.parseAndLoadModuleMapFile(*File, /* IsSystem = */ false,
|
|
/* ImplicitlyDiscovered = */ false,
|
|
File->getDir());
|
|
}
|
|
|
|
IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemFS;
|
|
IntrusiveRefCntPtr<InterceptorFS> VFS;
|
|
FileSystemOptions FileMgrOpts;
|
|
FileManager FileMgr;
|
|
DiagnosticOptions DiagnosticOpts;
|
|
DiagnosticsEngine Diagnostics;
|
|
SourceManager SrcMgr;
|
|
LangOptions LangOpts;
|
|
std::shared_ptr<TargetOptions> TargetOpts;
|
|
llvm::IntrusiveRefCntPtr<TargetInfo> Target;
|
|
HeaderSearchOptions HdrSearchOpts;
|
|
HeaderSearch HdrSearch;
|
|
|
|
ModuleMap Map;
|
|
};
|
|
|
|
// Regression test for
|
|
// https://github.com/llvm/llvm-project/issues/147220.
|
|
//
|
|
// These tests specifically aim to validate that ModuleMap paths do not grow
|
|
// in an unbounded fashion in the presence of chained relative paths to extern
|
|
// modules.
|
|
//
|
|
TEST_F(ModuleMapTest, ExternModuleRelativeLookupPathIsNormalized) {
|
|
// Root module as entry point, chained extern module references:
|
|
// A -> B -> C
|
|
addFile("/root/A.cppmap", R"(
|
|
module A {}
|
|
extern module B "../root/B.cppmap"
|
|
)");
|
|
addFile("/root/B.cppmap", R"(
|
|
module B {}
|
|
extern module C "../root/C.cppmap"
|
|
)");
|
|
// Leaf module
|
|
addFile("/root/C.cppmap", "module C {}");
|
|
|
|
ASSERT_FALSE(loadRoot("/root/A.cppmap"));
|
|
|
|
// Now check paths used are normalised.
|
|
llvm::SmallSet<llvm::StringRef, 4> Seen;
|
|
for (const std::string &Path : VFS->StatPaths) {
|
|
llvm::StringRef BaseName;
|
|
for (llvm::StringRef Component : llvm::make_range(
|
|
llvm::sys::path::begin(Path), llvm::sys::path::end(Path))) {
|
|
// As `/root/A.cppmap` is absolute, there should be no relative paths at
|
|
// lookup time.
|
|
EXPECT_NE(Component, "..");
|
|
// Last component is basename
|
|
BaseName = Component;
|
|
}
|
|
Seen.insert(BaseName);
|
|
}
|
|
|
|
// Ensure the path check covered all the modules we expected.
|
|
ASSERT_TRUE(Seen.contains("A.cppmap"));
|
|
ASSERT_TRUE(Seen.contains("B.cppmap"));
|
|
ASSERT_TRUE(Seen.contains("C.cppmap"));
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace clang
|