Refactor tests.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include "../Test.h"
|
||||
#include <Compiler/Resolver.h>
|
||||
|
||||
namespace {
|
||||
@@ -15,30 +15,28 @@ std::vector<const char*> compileArgs = {
|
||||
|
||||
struct Visitor : public clang::RecursiveASTVisitor<Visitor> {
|
||||
clang::QualType result;
|
||||
clang::QualType expect;
|
||||
std::unique_ptr<ParsedAST> parsedAST;
|
||||
|
||||
Visitor(const char* code) : parsedAST(ParsedAST::build("main.cpp", code, compileArgs)) {}
|
||||
Visitor(llvm::StringRef content) : parsedAST(ParsedAST::build("main.cpp", content, compileArgs)) {}
|
||||
|
||||
bool VisitTypeAliasDecl(clang::TypeAliasDecl* decl) {
|
||||
if(decl->getName() == "result") {
|
||||
auto type = decl->getUnderlyingType();
|
||||
{
|
||||
clang::Sema::CodeSynthesisContext context;
|
||||
context.Kind = clang::Sema::CodeSynthesisContext::TemplateInstantiation;
|
||||
context.Entity = decl;
|
||||
context.TemplateArgs = nullptr;
|
||||
parsedAST->sema.pushCodeSynthesisContext(context);
|
||||
}
|
||||
auto resolver = TemplateResolver(parsedAST->sema);
|
||||
result = resolver.resolve(type);
|
||||
TemplateResolver resolver(parsedAST->sema);
|
||||
result = resolver.resolve(decl->getUnderlyingType());
|
||||
}
|
||||
|
||||
if(decl->getName() == "expect") {
|
||||
expect = decl->getUnderlyingType();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
clang::QualType test() {
|
||||
void test() {
|
||||
auto decl = parsedAST->context.getTranslationUnitDecl();
|
||||
TraverseDecl(decl);
|
||||
return result;
|
||||
EXPECT_EQ(result.getCanonicalType(), expect.getCanonicalType());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -59,315 +57,24 @@ void match(clang::QualType type, std::string name, std::initializer_list<std::st
|
||||
}
|
||||
}
|
||||
|
||||
TEST(DependentNameResolver, single_level_dependent_name) {
|
||||
const char* code = R"(
|
||||
template <typename ...Ts>
|
||||
struct type_list {};
|
||||
|
||||
template <typename T>
|
||||
struct A {
|
||||
using type = type_list<T>;
|
||||
};
|
||||
|
||||
template <typename X>
|
||||
struct test {
|
||||
using result = typename A<X>::type;
|
||||
};
|
||||
|
||||
)";
|
||||
Visitor visitor(code);
|
||||
auto result = visitor.test();
|
||||
match(result, "type_list", {"X"});
|
||||
}
|
||||
|
||||
TEST(DependentNameResolver, multi_level_dependent_name) {
|
||||
const char* code = R"(
|
||||
template <typename ...Ts>
|
||||
struct type_list {};
|
||||
|
||||
template <typename T1>
|
||||
struct A {
|
||||
using type = type_list<T1>;
|
||||
};
|
||||
|
||||
template <typename T2>
|
||||
struct B {
|
||||
using type = typename A<T2>::type;
|
||||
};
|
||||
|
||||
template <typename T3>
|
||||
struct C {
|
||||
using type = typename B<T3>::type;
|
||||
};
|
||||
|
||||
template <typename X>
|
||||
struct test {
|
||||
using result = typename C<X>::type;
|
||||
};
|
||||
)";
|
||||
Visitor visitor(code);
|
||||
clang::QualType result = visitor.test();
|
||||
|
||||
match(result, "type_list", {"X"});
|
||||
}
|
||||
|
||||
TEST(DependentNameResolver, dependent_dependent_dependent_name) {
|
||||
const char* code = R"(
|
||||
template <typename ...Ts>
|
||||
struct type_list {};
|
||||
|
||||
template <typename T1>
|
||||
struct A {
|
||||
using self = A<T1>;
|
||||
using type = type_list<T1>;
|
||||
};
|
||||
|
||||
template <typename X>
|
||||
struct test {
|
||||
using result = typename A<X>::self::self::self::self::self::type;
|
||||
};
|
||||
)";
|
||||
Visitor visitor(code);
|
||||
clang::QualType result = visitor.test();
|
||||
|
||||
match(result, "type_list", {"X"});
|
||||
}
|
||||
|
||||
TEST(DependentNameResolver, alias_dependent_name) {
|
||||
const char* code = R"(
|
||||
template <typename ...Ts>
|
||||
struct type_list {};
|
||||
|
||||
template <typename T1>
|
||||
struct A {
|
||||
using type = type_list<T1>;
|
||||
};
|
||||
|
||||
template <typename T2>
|
||||
struct B {
|
||||
using base = A<T2>;
|
||||
using type = typename base::type;
|
||||
};
|
||||
|
||||
template <typename X>
|
||||
struct test {
|
||||
using result = typename B<X>::type;
|
||||
};
|
||||
)";
|
||||
Visitor visitor(code);
|
||||
clang::QualType result = visitor.test();
|
||||
match(result, "type_list", {"X"});
|
||||
}
|
||||
|
||||
TEST(DependentNameResolver, alias_template_dependent_name) {
|
||||
const char* code = R"(
|
||||
template <typename ...Ts>
|
||||
struct type_list {};
|
||||
|
||||
template <typename T1>
|
||||
struct A {
|
||||
using type = T1;
|
||||
};
|
||||
|
||||
template <typename T2>
|
||||
struct B {
|
||||
using base = A<T2>;
|
||||
using type = type_list<typename base::type>;
|
||||
};
|
||||
|
||||
template <typename X>
|
||||
struct test {
|
||||
using result = typename B<X>::type;
|
||||
};
|
||||
)";
|
||||
Visitor visitor(code);
|
||||
clang::QualType result = visitor.test();
|
||||
match(result, "type_list", {"X"});
|
||||
}
|
||||
|
||||
TEST(DependentNameResolver, template_alias_dependent_name) {
|
||||
const char* code = R"(
|
||||
template <typename ...Ts>
|
||||
struct type_list {};
|
||||
|
||||
template <typename T1>
|
||||
struct A {
|
||||
using type = type_list<T1>;
|
||||
};
|
||||
|
||||
template <typename T2>
|
||||
using B = A<T2>;
|
||||
|
||||
template <typename X>
|
||||
struct test {
|
||||
using result = typename B<X>::type;
|
||||
};
|
||||
)";
|
||||
Visitor visitor(code);
|
||||
clang::QualType result = visitor.test();
|
||||
match(result, "type_list", {"X"});
|
||||
}
|
||||
|
||||
TEST(DependentNameResolver, dependent_member_template) {
|
||||
const char* code = R"(
|
||||
template <typename... Ts>
|
||||
struct type_list {};
|
||||
|
||||
template <typename T1, typename U1>
|
||||
struct A {
|
||||
using type = type_list<T1, U1>;
|
||||
};
|
||||
|
||||
template <typename T2>
|
||||
struct B {
|
||||
template <typename U2>
|
||||
using type = typename A<T2, U2>::type;
|
||||
};
|
||||
|
||||
template <typename X, typename Y>
|
||||
struct test {
|
||||
using result = typename B<X>::template type<Y>;
|
||||
};
|
||||
)";
|
||||
Visitor visitor(code);
|
||||
clang::QualType result = visitor.test();
|
||||
match(result, "type_list", {"X", "Y"});
|
||||
}
|
||||
|
||||
TEST(DependentNameResolver, dependent_member_class_template) {
|
||||
const char* code = R"(
|
||||
template <typename... Ts>
|
||||
struct type_list {};
|
||||
|
||||
template <typename T1>
|
||||
struct A {
|
||||
template <typename U1>
|
||||
struct B {
|
||||
using type = type_list<T1, U1>;
|
||||
};
|
||||
};
|
||||
|
||||
template <typename X, typename Y>
|
||||
struct test {
|
||||
using result = typename A<X>::template B<Y>::type;
|
||||
};
|
||||
)";
|
||||
|
||||
Visitor visitor(code);
|
||||
clang::QualType result = visitor.test();
|
||||
match(result, "type_list", {"X", "Y"});
|
||||
}
|
||||
|
||||
TEST(DependentNameResolver, dependent_partial_name) {
|
||||
const char* code = R"(
|
||||
template <typename... Ts>
|
||||
struct type_list {};
|
||||
|
||||
template <typename T1>
|
||||
struct A {};
|
||||
|
||||
template <typename U2>
|
||||
struct B {};
|
||||
|
||||
template <typename U2, template <typename...> typename HKT>
|
||||
struct B<HKT<U2>> {
|
||||
using type = type_list<U2>;
|
||||
};
|
||||
|
||||
template <typename X>
|
||||
struct test {
|
||||
using result = typename B<A<X>>::type;
|
||||
};
|
||||
)";
|
||||
|
||||
Visitor visitor(code);
|
||||
clang::QualType result = visitor.test();
|
||||
result.dump();
|
||||
}
|
||||
|
||||
TEST(DependentNameResolver, dependent_base_name) {
|
||||
const char* code = R"(
|
||||
template <typename... Ts>
|
||||
struct type_list {};
|
||||
|
||||
template <typename T1>
|
||||
struct A {
|
||||
using type = type_list<T1>;
|
||||
};
|
||||
|
||||
template <typename U2>
|
||||
struct B : A<U2> {};
|
||||
|
||||
template <typename X>
|
||||
struct test {
|
||||
using result = typename B<X>::type;
|
||||
};
|
||||
)";
|
||||
|
||||
Visitor visitor(code);
|
||||
auto result = visitor.test();
|
||||
|
||||
match(result, "type_list", {"X"});
|
||||
}
|
||||
|
||||
TEST(DependentNameResolver, dependent_base_name_2) {
|
||||
const char* code = R"(
|
||||
template <typename... Ts>
|
||||
struct type_list {};
|
||||
|
||||
template <typename T1>
|
||||
struct A {
|
||||
using type = type_list<T1>;
|
||||
};
|
||||
|
||||
template <typename X>
|
||||
struct test {
|
||||
using base = typename A<X>::type;
|
||||
using result = base;
|
||||
};
|
||||
)";
|
||||
|
||||
Visitor visitor(code);
|
||||
auto result = visitor.test();
|
||||
llvm::outs() << "------------------------------------------\n";
|
||||
result.dump();
|
||||
match(result, "type_list", {"X"});
|
||||
}
|
||||
|
||||
TEST(DependentNameResolver, std_vector) {
|
||||
const char* code = R"(
|
||||
#include <vector>
|
||||
|
||||
template <typename T>
|
||||
struct A {};
|
||||
|
||||
template <typename X>
|
||||
struct test {
|
||||
using result = typename std::vector<X>::reference;
|
||||
};
|
||||
)";
|
||||
|
||||
Visitor visitor(code);
|
||||
clang::QualType result = visitor.test();
|
||||
llvm::outs() << "result is: { " << result.getAsString() << " }\n";
|
||||
}
|
||||
|
||||
TEST(DependentNameResolver, std_list) {
|
||||
const char* code = R"(
|
||||
#include <list>
|
||||
|
||||
template <typename T>
|
||||
struct A {};
|
||||
|
||||
template <typename X>
|
||||
struct test {
|
||||
using result = typename std::list<A<X>>::reference;
|
||||
};
|
||||
)";
|
||||
|
||||
Visitor visitor(code);
|
||||
clang::QualType result = visitor.test();
|
||||
llvm::outs() << "result is: { " << result.getAsString() << " }\n";
|
||||
TEST(clice, TemplateResolver) {
|
||||
// FIXME: more flexible
|
||||
auto path = test_dir() + "/TemplateResolver";
|
||||
std::error_code error;
|
||||
fs::directory_iterator iter(path, error);
|
||||
fs::directory_iterator end;
|
||||
while(!error && iter != end) {
|
||||
auto file = iter->path();
|
||||
llvm::outs() << "test: " << file << " " << error.message() << "\n";
|
||||
auto buffer = llvm::MemoryBuffer::getFile(file);
|
||||
if(!buffer) {
|
||||
llvm::outs() << "failed to open file: " << buffer.getError().message() << file << "\n";
|
||||
}
|
||||
auto content = buffer.get()->getBuffer();
|
||||
Visitor visitor(content);
|
||||
visitor.test();
|
||||
iter.increment(error);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user