#include "../Test.h" #include #include namespace clice { namespace { void run(llvm::StringRef code, std::source_location current = std::source_location::current()) { Tester tester("main.cpp", code); tester.run(); struct Run : clang::RecursiveASTVisitor { ASTInfo& info; clang::QualType input; clang::QualType expect; using Base = clang::RecursiveASTVisitor; Run(ASTInfo& info) : info(info) {} bool TraverseDecl(clang::Decl* decl) { if(decl && (llvm::isa(decl) || info.srcMgr().isInMainFile(decl->getLocation()))) { return Base::TraverseDecl(decl); } return true; } bool VisitTypedefNameDecl(const clang::TypedefNameDecl* decl) { if(decl->getName() == "input") { input = decl->getUnderlyingType(); } if(decl->getName() == "expect") { expect = decl->getUnderlyingType(); } return true; } }; Run run{tester.info}; run.TraverseAST(tester.info.context()); auto input = tester.info.resolver().resolve(run.input); auto expect = run.expect; EXPECT_EQ(input.isNull(), false, current); EXPECT_EQ(expect.isNull(), false, current); EXPECT_EQ(input.getCanonicalType(), expect.getCanonicalType(), current); } TEST(TemplateResolver, TypeParameterType) { run(R"cpp( template struct A { using type = T; }; template struct test { using input = typename A::type; using expect = X; }; )cpp"); } TEST(TemplateResolver, SingleLevel) { run(R"cpp( template struct type_list {}; template struct A { using type = type_list; }; template struct test { using input = typename A::type; using expect = type_list; }; )cpp"); } TEST(TemplateResolver, SingleLevelNotDependent) { run(R"cpp( template struct A { using type = int; }; template struct test { using input = typename A::type; using expect = int; }; )cpp"); } TEST(TemplateResolver, MultiLevel) { run(R"cpp( template struct type_list {}; template struct A { using type = type_list; }; template struct B { using type = typename A::type; }; template struct C { using type = typename B::type; }; template struct test { using input = typename C::type; using expect = type_list; }; )cpp"); } TEST(TemplateResolver, MultiLevelNotDependent) { run(R"cpp( template struct A { using type = int; }; template struct B { using type = typename A::type; }; template struct C { using type = typename B::type; }; template struct test { using input = typename C::type; using expect = int; }; )cpp"); } TEST(TemplateResolver, ArgumentDependent) { run(R"cpp( template struct type_list {}; template struct A { using type = T1; }; template struct B { using type = type_list; }; template struct test { using input = typename B::type>::type; using expect = type_list; }; )cpp"); } TEST(TemplateResolver, AliasArgument) { run(R"cpp( template struct type_list {}; template struct A { using type = T1; }; template struct B { using base = A; using type = type_list; }; template struct test { using input = typename B::type; using expect = type_list; }; )cpp"); } TEST(TemplateResolver, AliasDependent) { run(R"cpp( template struct type_list {}; template struct A { using type = type_list; }; template struct B { using base = A; using type = typename base::type; }; template struct test { using input = typename B::type; using expect = type_list; }; )cpp"); } TEST(TemplateResolver, AliasTemplate) { run(R"cpp( template struct type_list {}; template struct A { using type = type_list; }; template struct B { template using type = typename A::type; }; template struct test { using input = typename B::template type; using expect = type_list; }; )cpp"); } TEST(TemplateResolver, BaseDependent) { run(R"cpp( template struct type_list {}; template struct A { using type = type_list; }; template struct B : A {}; template struct test { using input = typename B::type; using expect = type_list; }; )cpp"); } TEST(TemplateResolver, MultiNested) { run(R"cpp( template struct type_list {}; template struct A { using self = A; using type = type_list; }; template struct test { using input = typename A::self::self::self::self::self::type; using expect = type_list; }; )cpp"); } TEST(TemplateResolver, OuterDependentMemberClass) { run(R"cpp( template struct type_list {}; template struct A { template struct B { template struct C { using type = type_list; }; }; }; template struct test { using input = typename A::template B::template C::type; using expect = type_list; }; )cpp"); } TEST(TemplateResolver, InnerDependentMemberClass) { run(R"cpp( template struct type_list {}; template struct test { template struct B { using type = type_list; }; using input = typename B<1, T>::type; using expect = type_list; }; )cpp"); } TEST(TemplateResolver, InnerDependentPartialMemberClass) { run(R"cpp( template struct type_list {}; template struct test {}; template struct test { template struct A { using type = type_list; }; using input = typename A<1, T>::type; using expect = type_list; }; )cpp"); } TEST(TemplateResolver, PartialSpecialization) { run(R"cpp( template struct type_list {}; template struct A {}; template struct B {}; template typename HKT> struct B> { using type = type_list; }; template struct test { using input = typename B>::type; using expect = type_list; }; )cpp"); } TEST(TemplateResolver, PartialDefaultArgument) { run(R"cpp( template struct X {}; template struct X { using type = T; }; template struct test { using input = typename X::type; using expect = T; }; )cpp"); } TEST(TemplateResolver, DefaultArgument) { run(R"cpp( template struct type_list {}; template struct A { using type = type_list; }; template > struct B { using type = typename U2::type; }; template struct test { using input = typename B::type; using expect = type_list; }; )cpp"); } TEST(TemplateResolver, PackExpansion) { run(R"cpp( template struct type_list {}; template struct X { using type = type_list; }; template struct test { using input = typename X::type; using expect = type_list; }; )cpp"); } TEST(TemplateResolver, BasePackExpansion) { run(R"cpp( template struct type_list {}; template struct X { using type = type_list; }; template struct Y : X {}; template struct test { using input = typename Y::type; using expect = type_list; }; )cpp"); } TEST(TemplateResolver, Standard) { run(R"cpp( #include template struct test { using input = typename std::vector::reference; using expect = T&; }; )cpp"); } } // namespace } // namespace clice