Files
TheRock/compiler/amd-llvm/clang/unittests/Lex/PPDependencyDirectivesTest.cpp
T
derek.holloway 7502bf64a4
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
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

236 lines
8.6 KiB
C++

//===- unittests/Lex/PPDependencyDirectivesTest.cpp -------------------------=//
//
// 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/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/TargetOptions.h"
#include "clang/Lex/DependencyDirectivesScanner.h"
#include "clang/Lex/HeaderSearch.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/ModuleLoader.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Lex/PreprocessorOptions.h"
#include "llvm/Testing/Support/Error.h"
#include "gtest/gtest.h"
#include <optional>
using namespace clang;
namespace {
// The test fixture.
class PPDependencyDirectivesTest : public ::testing::Test {
protected:
PPDependencyDirectivesTest()
: FileMgr(FileMgrOpts),
Diags(DiagnosticIDs::create(), DiagOpts, new IgnoringDiagConsumer()),
SourceMgr(Diags, FileMgr), TargetOpts(new TargetOptions) {
TargetOpts->Triple = "x86_64-apple-macos12";
Target = TargetInfo::CreateTargetInfo(Diags, *TargetOpts);
}
FileSystemOptions FileMgrOpts;
FileManager FileMgr;
DiagnosticOptions DiagOpts;
DiagnosticsEngine Diags;
SourceManager SourceMgr;
LangOptions LangOpts;
std::shared_ptr<TargetOptions> TargetOpts;
IntrusiveRefCntPtr<TargetInfo> Target;
};
class IncludeCollector : public PPCallbacks {
public:
Preprocessor &PP;
SmallVectorImpl<StringRef> &IncludedFiles;
IncludeCollector(Preprocessor &PP, SmallVectorImpl<StringRef> &IncludedFiles)
: PP(PP), IncludedFiles(IncludedFiles) {}
void LexedFileChanged(FileID FID, LexedFileChangeReason Reason,
SrcMgr::CharacteristicKind FileType, FileID PrevFID,
SourceLocation Loc) override {
if (Reason != LexedFileChangeReason::EnterFile)
return;
if (FID == PP.getPredefinesFileID())
return;
StringRef Filename =
PP.getSourceManager().getSLocEntry(FID).getFile().getName();
IncludedFiles.push_back(Filename);
}
};
class EmbedCollector : public PPCallbacks {
public:
Preprocessor &PP;
SmallVectorImpl<StringRef> &EmbeddedFiles;
EmbedCollector(Preprocessor &PP, SmallVectorImpl<StringRef> &EmbeddedFiles)
: PP(PP), EmbeddedFiles(EmbeddedFiles) {}
void EmbedDirective(SourceLocation, StringRef, bool,
OptionalFileEntryRef File,
const LexEmbedParametersResult &) override {
assert(File && "expected to only be called when the file is found");
StringRef Filename =
llvm::sys::path::remove_leading_dotslash(File->getName());
EmbeddedFiles.push_back(Filename);
}
void HasEmbed(SourceLocation, StringRef, bool,
OptionalFileEntryRef File) override {
if (!File)
return;
StringRef Filename =
llvm::sys::path::remove_leading_dotslash(File->getName());
EmbeddedFiles.push_back(Filename);
}
};
TEST_F(PPDependencyDirectivesTest, MacroGuard) {
// "head1.h" has a macro guard and should only be included once.
// "head2.h" and "head3.h" have tokens following the macro check, they should
// be included multiple times.
auto VFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
VFS->addFile(
"head1.h", 0,
llvm::MemoryBuffer::getMemBuffer("#ifndef H1_H\n#define H1_H\n#endif\n"));
VFS->addFile(
"head2.h", 0,
llvm::MemoryBuffer::getMemBuffer("#ifndef H2_H\n#define H2_H\n#endif\n\n"
"extern int foo;\n"));
VFS->addFile("head3.h", 0,
llvm::MemoryBuffer::getMemBuffer(
"#ifndef H3_H\n#define H3_H\n#endif\n\n"
"#ifdef SOMEMAC\nextern int foo;\n#endif\n"));
VFS->addFile("main.c", 0,
llvm::MemoryBuffer::getMemBuffer(
"#include \"head1.h\"\n#include \"head1.h\"\n"
"#include \"head2.h\"\n#include \"head2.h\"\n"
"#include \"head3.h\"\n#include \"head3.h\"\n"));
FileMgr.setVirtualFileSystem(VFS);
OptionalFileEntryRef FE;
ASSERT_THAT_ERROR(FileMgr.getFileRef("main.c").moveInto(FE),
llvm::Succeeded());
SourceMgr.setMainFileID(
SourceMgr.createFileID(*FE, SourceLocation(), SrcMgr::C_User));
struct DepDirectives {
SmallVector<dependency_directives_scan::Token> Tokens;
SmallVector<dependency_directives_scan::Directive> Directives;
};
class TestDependencyDirectivesGetter : public DependencyDirectivesGetter {
FileManager &FileMgr;
SmallVector<std::unique_ptr<DepDirectives>> DepDirectivesObjects;
public:
TestDependencyDirectivesGetter(FileManager &FileMgr) : FileMgr(FileMgr) {}
std::unique_ptr<DependencyDirectivesGetter>
cloneFor(FileManager &FileMgr) override {
return std::make_unique<TestDependencyDirectivesGetter>(FileMgr);
}
std::optional<ArrayRef<dependency_directives_scan::Directive>>
operator()(FileEntryRef File) override {
DepDirectivesObjects.push_back(std::make_unique<DepDirectives>());
StringRef Input = (*FileMgr.getBufferForFile(File))->getBuffer();
bool Err = scanSourceForDependencyDirectives(
Input, DepDirectivesObjects.back()->Tokens,
DepDirectivesObjects.back()->Directives);
EXPECT_FALSE(Err);
return DepDirectivesObjects.back()->Directives;
}
};
TestDependencyDirectivesGetter GetDependencyDirectives(FileMgr);
PreprocessorOptions PPOpts;
HeaderSearchOptions HSOpts;
TrivialModuleLoader ModLoader;
HeaderSearch HeaderInfo(HSOpts, SourceMgr, Diags, LangOpts, Target.get());
Preprocessor PP(PPOpts, Diags, LangOpts, SourceMgr, HeaderInfo, ModLoader,
/*IILookup =*/nullptr,
/*OwnsHeaderSearch =*/false);
PP.Initialize(*Target);
PP.setDependencyDirectivesGetter(GetDependencyDirectives);
SmallVector<StringRef> IncludedFiles;
PP.addPPCallbacks(std::make_unique<IncludeCollector>(PP, IncludedFiles));
PP.EnterMainSourceFile();
PP.LexTokensUntilEOF();
SmallVector<std::string> IncludedFilesSlash;
for (StringRef IncludedFile : IncludedFiles)
IncludedFilesSlash.push_back(
llvm::sys::path::convert_to_slash(IncludedFile));
SmallVector<std::string> ExpectedIncludes{
"main.c", "./head1.h", "./head2.h", "./head2.h", "./head3.h", "./head3.h",
};
EXPECT_EQ(IncludedFilesSlash, ExpectedIncludes);
}
TEST_F(PPDependencyDirectivesTest, Embed) {
auto VFS = llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();
VFS->setCurrentWorkingDirectory("/source");
VFS->addFile("/source/inputs/jk.txt", 0,
llvm::MemoryBuffer::getMemBuffer("jk"));
VFS->addFile("/source/inputs/single_byte.txt", 0,
llvm::MemoryBuffer::getMemBuffer("a"));
VFS->addFile("/source/inputs/single_byte1.txt", 0,
llvm::MemoryBuffer::getMemBuffer("b"));
VFS->addFile(
"/source/inc/head.h", 0,
llvm::MemoryBuffer::getMemBuffer("#embed \"inputs/single_byte.txt\"\n"
"extern int foo;\n"));
VFS->addFile(
"main.c", 0,
llvm::MemoryBuffer::getMemBuffer("#include \"inc/head.h\"\n"
"#if __has_embed(\"inputs/jk.txt\")\n"
"const char arr[] =\n"
"#embed \"inputs/single_byte1.txt\"\n"
";\n"
"#endif\n"));
FileMgr.setVirtualFileSystem(VFS);
OptionalFileEntryRef FE;
ASSERT_THAT_ERROR(FileMgr.getFileRef("main.c").moveInto(FE),
llvm::Succeeded());
SourceMgr.setMainFileID(
SourceMgr.createFileID(*FE, SourceLocation(), SrcMgr::C_User));
PreprocessorOptions PPOpts;
HeaderSearchOptions HSOpts;
TrivialModuleLoader ModLoader;
HeaderSearch HeaderInfo(HSOpts, SourceMgr, Diags, LangOpts, Target.get());
Preprocessor PP(PPOpts, Diags, LangOpts, SourceMgr, HeaderInfo, ModLoader,
/*IILookup =*/nullptr,
/*OwnsHeaderSearch =*/false);
PP.Initialize(*Target);
SmallVector<StringRef> EmbeddedFiles;
PP.addPPCallbacks(std::make_unique<EmbedCollector>(PP, EmbeddedFiles));
PP.EnterMainSourceFile();
PP.LexTokensUntilEOF();
SmallVector<StringRef> ExpectedEmbeds{
"inputs/single_byte.txt",
"inputs/jk.txt",
"inputs/single_byte1.txt",
};
EXPECT_EQ(EmbeddedFiles, ExpectedEmbeds);
}
} // anonymous namespace