diff --git a/include/AST/Resolver.h b/include/AST/Resolver.h index a05db5ca..5d339a42 100644 --- a/include/AST/Resolver.h +++ b/include/AST/Resolver.h @@ -24,6 +24,8 @@ public: clang::QualType resolve(const clang::DependentNameType* DNT); + clang::QualType resolve(const clang::DependentTemplateSpecializationType* DTST); + /// lookup member in a given nested name specifier bool lookup(llvm::SmallVector& result, const clang::NestedNameSpecifier* NNS, diff --git a/src/AST/Resolver.cpp b/src/AST/Resolver.cpp index 2767a36a..c6f475eb 100644 --- a/src/AST/Resolver.cpp +++ b/src/AST/Resolver.cpp @@ -21,6 +21,8 @@ clang::QualType DependentNameResolver::resolve(clang::QualType type) { if(auto DNT = llvm::dyn_cast(type)) { return resolve(DNT); + } else if(auto DTST = llvm::dyn_cast(type)) { + return resolve(DTST); } else { return type; } @@ -36,6 +38,19 @@ clang::QualType DependentNameResolver::resolve(const clang::DependentNameType* D } } +clang::QualType DependentNameResolver::resolve(const clang::DependentTemplateSpecializationType* DTST) { + llvm::SmallVector result; + if(lookup(result, DTST->getQualifier(), DTST->getIdentifier()) && result.size() == 1) { + if(auto TATD = llvm::dyn_cast(result.front())) { + frames.emplace_back(TATD, DTST->template_arguments()); + return resolve(substitute(TATD->getTemplatedDecl()->getUnderlyingType())); + } + } + + DTST->dump(); + std::terminate(); +} + bool DependentNameResolver::lookup(llvm::SmallVector& result, const clang::NestedNameSpecifier* NNS, const clang::IdentifierInfo* II) { @@ -68,13 +83,22 @@ bool DependentNameResolver::lookup(llvm::SmallVector& result, bool DependentNameResolver::lookup(llvm::SmallVector& result, const clang::QualType type, const clang::IdentifierInfo* II) { + + clang::TemplateDecl* TD; + llvm::ArrayRef args; + + // FIXME: consider default arguments if(auto TST = type->getAs()) { - auto TD = TST->getTemplateName().getAsTemplateDecl(); - // FIXME: consider default arguments - auto args = TST->template_arguments(); - if(auto CTD = llvm::dyn_cast(TD)) { - return lookup(result, CTD, II, args); - } + TD = TST->getTemplateName().getAsTemplateDecl(); + args = TST->template_arguments(); + } else if(auto DTST = type->getAs()) { + } + + if(auto CTD = llvm::dyn_cast(TD)) { + return lookup(result, CTD, II, args); + } else if(auto TATD = llvm::dyn_cast(TD)) { + frames.emplace_back(TATD, args); + return lookup(result, resolve(substitute(TATD->getTemplatedDecl()->getUnderlyingType())), II); } std::terminate(); diff --git a/tests/Resolver.cpp b/tests/Resolver.cpp index e159cf4c..95733da5 100644 --- a/tests/Resolver.cpp +++ b/tests/Resolver.cpp @@ -180,5 +180,77 @@ struct test { ASSERT_EQ(T->getDecl()->getName(), "X"); } +TEST(DependentNameResolver, template_alias_dependent_name) { + const char* code = R"( +template +struct type_list {}; + +template +struct A { + using type = type_list; +}; + +template +using B = A; + +template +struct test { + using result = typename B::type; +}; +)"; + Visitor visitor(code); + clang::QualType result = visitor.test(); + // result->dump(); + auto TST = result->getAs(); + ASSERT_TRUE(TST); + ASSERT_EQ(TST->getTemplateName().getAsTemplateDecl()->getName(), "type_list"); + + auto args = TST->template_arguments(); + ASSERT_EQ(args.size(), 1); + + auto T = llvm::dyn_cast(args[0].getAsType()); + ASSERT_TRUE(T); + ASSERT_EQ(T->getDecl()->getName(), "X"); +} + +TEST(DependentNameResolver, dependent_member_template) { + const char* code = R"( +template +struct type_list {}; + +template +struct A { + using type = type_list; +}; + +template +struct B { + template + using type = typename A::type; +}; + +template +struct test { + using result = typename B::template type; +}; +)"; + Visitor visitor(code); + clang::QualType result = visitor.test(); + auto TST = result->getAs(); + 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(args[0].getAsType()); + ASSERT_TRUE(X); + ASSERT_EQ(X->getDecl()->getName(), "X"); + + auto Y = llvm::dyn_cast(args[1].getAsType()); + ASSERT_TRUE(Y); + ASSERT_EQ(Y->getDecl()->getName(), "Y"); +} + } // namespace