99#include < clang/Basic/OperatorKinds.h>
1010#include < clang/Basic/SourceManager.h>
1111#include < clang/Lex/Lexer.h>
12+ #include < clang/Sema/Sema.h>
13+ #include < clang/Sema/TemplateDeduction.h>
1214#include < llvm/ADT/STLExtras.h>
1315
1416#include < cassert>
@@ -56,32 +58,51 @@ const clang::Decl *getParent(const clang::Decl *decl) {
5658 return nullptr ;
5759}
5860
59- std::vector<clang::QualType> resolveMemberType (clang::QualType type) {
61+ llvm::SmallVector<clang::CXXRecordDecl *>
62+ matchingDefinitions (clang::Sema &sema, clang::ClassTemplateDecl *tmpl,
63+ const clang::TemplateSpecializationType *spec) {
64+ llvm::SmallVector<clang::ClassTemplatePartialSpecializationDecl *> partials;
65+ tmpl->getPartialSpecializations (partials);
66+ llvm::SmallVector<clang::CXXRecordDecl *> records;
67+ for (auto partial : partials) {
68+ RuleDecls::Trial trial (sema);
69+ clang::sema::TemplateDeductionInfo info (partial->getLocation ());
70+ if (sema.DeduceTemplateArguments (partial, spec->template_arguments (),
71+ info) ==
72+ clang::TemplateDeductionResult::Success &&
73+ !trial.failed ()) {
74+ records.push_back (partial);
75+ }
76+ }
77+ if (records.empty ()) {
78+ records.push_back (tmpl->getTemplatedDecl ());
79+ }
80+ return records;
81+ }
82+
83+ std::vector<clang::QualType> resolveMemberType (clang::Sema &sema,
84+ clang::QualType type) {
6085 auto member = type->getAs <clang::DependentNameType>();
6186 if (!member) {
6287 return {type};
6388 }
6489 auto qualifier = member->getQualifier ().getAsType ();
6590 assert (qualifier && " member type is not qualified by a type" );
6691 std::vector<clang::QualType> resolved;
67- for (auto owner : resolveMemberType (clang::QualType (qualifier, 0 ))) {
92+ for (auto owner : resolveMemberType (sema, clang::QualType (qualifier, 0 ))) {
6893 auto spec = owner->getAs <clang::TemplateSpecializationType>();
6994 auto tmpl = spec ? llvm::dyn_cast_or_null<clang::ClassTemplateDecl>(
7095 spec->getTemplateName ().getAsTemplateDecl ())
7196 : nullptr ;
7297 assert (tmpl && " member type is not qualified by a class template" );
73- llvm::SmallVector<clang::ClassTemplatePartialSpecializationDecl *> partials;
74- tmpl->getPartialSpecializations (partials);
75- llvm::SmallVector<clang::CXXRecordDecl *> records{tmpl->getTemplatedDecl ()};
76- records.append (partials.begin (), partials.end ());
77- for (auto record : records) {
98+ for (auto record : matchingDefinitions (sema, tmpl, spec)) {
7899 if (!record->hasDefinition ()) {
79100 continue ;
80101 }
81102 for (auto decl :
82103 record->getDefinition ()->lookup (member->getIdentifier ())) {
83104 if (auto alias = llvm::dyn_cast<clang::TypedefNameDecl>(decl)) {
84- auto types = resolveMemberType (alias->getUnderlyingType ());
105+ auto types = resolveMemberType (sema, alias->getUnderlyingType ());
85106 resolved.insert (resolved.end (), types.begin (), types.end ());
86107 }
87108 }
@@ -198,8 +219,9 @@ std::optional<ExprKey> GetExprKey(clang::ASTContext &ctx,
198219 return std::nullopt ;
199220}
200221
201- std::vector<ExprKey> GetExprKeys (clang::ASTContext &ctx ,
222+ std::vector<ExprKey> GetExprKeys (clang::Sema &sema ,
202223 const clang::NamedDecl *rule) {
224+ auto &ctx = sema.Context ;
203225 if (auto var = llvm::dyn_cast<clang::VarDecl>(rule)) {
204226 auto key = GetExprKey (ctx, var->getInit ());
205227 assert (key && " expression rule has no key" );
@@ -210,7 +232,7 @@ std::vector<ExprKey> GetExprKeys(clang::ASTContext &ctx,
210232 if (auto construct =
211233 llvm::dyn_cast<clang::CXXUnresolvedConstructExpr>(returned)) {
212234 std::vector<ExprKey> keys;
213- for (auto type : resolveMemberType (construct->getTypeAsWritten ())) {
235+ for (auto type : resolveMemberType (sema, construct->getTypeAsWritten ())) {
214236 if (type->getAs <clang::TemplateTypeParmType>()) {
215237 if (!llvm::is_contained (keys, ExprKey{kAnyConstructor })) {
216238 keys.push_back (kAnyConstructor );
0 commit comments