Files
clice/unittests/Compiler/Directive.cpp

202 lines
5.3 KiB
C++

#include "Test/CTest.h"
#include "Basic/SourceConverter.h"
namespace clice::testing {
namespace {
struct Directive : ::testing::Test, Tester {
clang::SourceManager* SM;
llvm::ArrayRef<Include> includes;
llvm::ArrayRef<HasInclude> hasIncludes;
llvm::ArrayRef<Condition> conditions;
llvm::ArrayRef<MacroRef> macros;
void run(const char* standard = "-std=c++20") {
Tester::run("-std=c++23");
SM = &info->srcMgr();
auto fid = SM->getMainFileID();
includes = info->directives()[fid].includes;
hasIncludes = info->directives()[fid].hasIncludes;
conditions = info->directives()[fid].conditions;
macros = info->directives()[fid].macros;
}
void EXPECT_INCLUDE(std::size_t index,
llvm::StringRef position,
llvm::StringRef path,
std::source_location current = std::source_location::current()) {
auto& include = includes[index];
auto entry = SM->getFileEntryRefForID(include.fid);
EXPECT_EQ(SourceConverter().toPosition(include.location, *SM), pos(position), current);
EXPECT_EQ(entry ? entry->getName() : "", path, current);
}
void EXPECT_HAS_INCLUDE(std::size_t index,
llvm::StringRef position,
llvm::StringRef path,
std::source_location current = std::source_location::current()) {
auto& hasInclude = hasIncludes[index];
EXPECT_EQ(SourceConverter().toPosition(hasInclude.location, *SM), pos(position), current);
EXPECT_EQ(hasInclude.path, path, current);
}
void EXPECT_CON(std::size_t index,
Condition::BranchKind kind,
llvm::StringRef position,
std::source_location current = std::source_location::current()) {
auto& condition = conditions[index];
EXPECT_EQ(condition.kind, kind, current);
EXPECT_EQ(SourceConverter().toPosition(condition.loc, *SM), pos(position), current);
}
void EXPECT_MACRO(std::size_t index,
MacroRef::Kind kind,
llvm::StringRef position,
std::source_location current = std::source_location::current()) {
auto& macro = macros[index];
EXPECT_EQ(macro.kind, kind, current);
EXPECT_EQ(SourceConverter().toPosition(macro.loc, *SM), pos(position), current);
}
};
TEST_F(Directive, Include) {
const char* test = "";
const char* test2 = R"cpp(
#include "test.h"
)cpp";
const char* pragma_once = R"cpp(
#pragma once
)cpp";
const char* guard_macro = R"cpp(
#ifndef TEST3_H
#define TEST3_H
#endif
)cpp";
const char* main = R"cpp(
#$(0)include "test.h"
#$(1)include "test.h"
#$(2)include "pragma_once.h"
#$(3)include "pragma_once.h"
#$(4)include "guard_macro.h"
#$(5)include "guard_macro.h"
)cpp";
addMain("main.cpp", main);
using Path = llvm::SmallString<128>;
Path ptest, ppragma_once, pguard_macro;
path::append(ptest, ".", "test.h");
path::append(ppragma_once, ".", "pragma_once.h");
path::append(pguard_macro, ".", "guard_macro.h");
addFile(ptest, test);
addFile(ppragma_once, pragma_once);
addFile(pguard_macro, guard_macro);
run();
EXPECT_EQ(includes.size(), 6);
EXPECT_INCLUDE(0, "0", ptest);
EXPECT_INCLUDE(1, "1", ptest);
EXPECT_INCLUDE(2, "2", ppragma_once);
EXPECT_INCLUDE(3, "3", "");
EXPECT_INCLUDE(4, "4", pguard_macro);
EXPECT_INCLUDE(5, "5", "");
}
TEST_F(Directive, HasInclude) {
const char* test = "";
const char* main = R"cpp(
#if __has_include($(0)"test.h")
#endif
)cpp";
addMain("main.cpp", main);
llvm::SmallString<128> path;
path::append(path, ".", "test.h");
addFile(path, test);
run();
EXPECT_EQ(hasIncludes.size(), 1);
EXPECT_HAS_INCLUDE(0, "0", path);
}
TEST_F(Directive, Condition) {
const char* code = R"cpp(
#$(0)if 0
#$(1)elif 1
#$(2)else
#$(3)endif
#$(4)ifdef name
#$(5)elifdef name
#$(6)else
#$(7)endif
)cpp";
addMain("main.cpp", code);
run("-std=c++23");
EXPECT_EQ(conditions.size(), 8);
EXPECT_CON(0, Condition::BranchKind::If, "0");
EXPECT_CON(1, Condition::BranchKind::Elif, "1");
EXPECT_CON(2, Condition::BranchKind::Else, "2");
EXPECT_CON(3, Condition::BranchKind::EndIf, "3");
EXPECT_CON(4, Condition::BranchKind::Ifdef, "4");
EXPECT_CON(5, Condition::BranchKind::Elifdef, "5");
EXPECT_CON(6, Condition::BranchKind::Else, "6");
EXPECT_CON(7, Condition::BranchKind::EndIf, "7");
}
TEST_F(Directive, Macro) {
const char* code = R"cpp(
#define $(0)expr(v) v
#ifdef $(1)expr
int x = $(2)expr(1);
#endif
#undef $(3)expr
#define $(4)expr(v) v
#ifdef $(5)expr
int y = $(6)expr($(7)expr(1));
#endif
#undef $(8)expr
)cpp";
addMain("main.cpp", code);
run();
EXPECT_EQ(macros.size(), 9);
EXPECT_MACRO(0, MacroRef::Kind::Def, "0");
EXPECT_MACRO(1, MacroRef::Kind::Ref, "1");
EXPECT_MACRO(2, MacroRef::Kind::Ref, "2");
EXPECT_MACRO(3, MacroRef::Kind::Undef, "3");
EXPECT_MACRO(4, MacroRef::Kind::Def, "4");
EXPECT_MACRO(5, MacroRef::Kind::Ref, "5");
EXPECT_MACRO(6, MacroRef::Kind::Ref, "6");
EXPECT_MACRO(7, MacroRef::Kind::Ref, "7");
EXPECT_MACRO(8, MacroRef::Kind::Undef, "8");
}
} // namespace
} // namespace clice::testing