Resolver now can handle inner template class!
This commit is contained in:
@@ -92,6 +92,13 @@ bool DependentNameResolver::lookup(llvm::SmallVector<clang::NamedDecl*>& result,
|
||||
TD = TST->getTemplateName().getAsTemplateDecl();
|
||||
args = TST->template_arguments();
|
||||
} else if(auto DTST = type->getAs<clang::DependentTemplateSpecializationType>()) {
|
||||
if(lookup(result, DTST->getQualifier(), DTST->getIdentifier()) && result.size() == 1) {
|
||||
TD = llvm::dyn_cast<clang::TemplateDecl>(result.front());
|
||||
args = DTST->template_arguments();
|
||||
result.clear();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(auto CTD = llvm::dyn_cast<clang::ClassTemplateDecl>(TD)) {
|
||||
@@ -143,7 +150,8 @@ bool DependentNameResolver::lookup(llvm::SmallVector<clang::NamedDecl*>& result,
|
||||
// NOTE: takeSugared will take the ownership of the list
|
||||
auto list = info.takeSugared();
|
||||
frames.emplace_back(partial, list->asArray());
|
||||
delete list;
|
||||
// FIXME: should we delete the list?
|
||||
// delete list;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -162,7 +170,10 @@ static bool isalias(clang::QualType type) {
|
||||
return false;
|
||||
} else if(auto DNT = type->getAs<clang::DependentNameType>()) {
|
||||
return isalias(clang::QualType(DNT->getQualifier()->getAsType(), 0));
|
||||
} else if(auto LVRT = type->getAs<clang::LValueReferenceType>()) {
|
||||
return isalias(LVRT->getPointeeType());
|
||||
} else {
|
||||
type.dump();
|
||||
std::terminate();
|
||||
}
|
||||
}
|
||||
@@ -178,6 +189,8 @@ clang::QualType DependentNameResolver::dealias(clang::QualType type) {
|
||||
auto type = dealias(clang::QualType(DNT->getQualifier()->getAsType(), 0));
|
||||
auto prefix = clang::NestedNameSpecifier::Create(context, nullptr, false, type.getTypePtr());
|
||||
return context.getDependentNameType(DNT->getKeyword(), prefix, DNT->getIdentifier());
|
||||
} else if(auto LVRT = type->getAs<clang::LValueReferenceType>()) {
|
||||
return context.getLValueReferenceType(dealias(LVRT->getPointeeType()));
|
||||
} else {
|
||||
std::terminate();
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ std::vector<const char*> compileArgs = {
|
||||
"clang++",
|
||||
"-std=c++20",
|
||||
"main.cpp",
|
||||
"-resource-dir=../build/lib/clang/20",
|
||||
"-resource-dir=/home/ykiko/C++/clice2/build/lib/clang/20",
|
||||
};
|
||||
|
||||
struct Visitor : public clang::RecursiveASTVisitor<Visitor> {
|
||||
@@ -252,5 +252,85 @@ struct test {
|
||||
ASSERT_EQ(Y->getDecl()->getName(), "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();
|
||||
|
||||
auto TST = result->getAs<clang::TemplateSpecializationType>();
|
||||
ASSERT_TRUE(TST);
|
||||
ASSERT_EQ(TST->getTemplateName().getAsTemplateDecl()->getName(), "type_list");
|
||||
|
||||
auto args = TST->template_arguments();
|
||||
ASSERT_EQ(args.size(), 2);
|
||||
|
||||
auto X = llvm::dyn_cast<clang::TemplateTypeParmType>(args[0].getAsType());
|
||||
ASSERT_TRUE(X);
|
||||
ASSERT_EQ(X->getDecl()->getName(), "X");
|
||||
|
||||
auto Y = llvm::dyn_cast<clang::TemplateTypeParmType>(args[1].getAsType());
|
||||
ASSERT_TRUE(Y);
|
||||
ASSERT_EQ(Y->getDecl()->getName(), "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, std_vector) {
|
||||
// const char* code = R"(
|
||||
// #include <vector>
|
||||
//
|
||||
// template <typename T>
|
||||
// struct test {
|
||||
// using result = typename std::vector<T, std::allocator<T>>::reference;
|
||||
// };
|
||||
//)";
|
||||
//
|
||||
// Visitor visitor(code);
|
||||
// clang::QualType result = visitor.test();
|
||||
// result->dump();
|
||||
// }
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
Reference in New Issue
Block a user