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 }
@@ -203,8 +224,9 @@ std::optional<ExprKey> GetExprKey(clang::ASTContext &ctx,
203224 return getExprKey (ctx, use);
204225}
205226
206- std::vector<ExprKey> GetExprKeys (clang::ASTContext &ctx ,
227+ std::vector<ExprKey> GetExprKeys (clang::Sema &sema ,
207228 const clang::NamedDecl *rule) {
229+ auto &ctx = sema.Context ;
208230 if (auto var = llvm::dyn_cast<clang::VarDecl>(rule)) {
209231 auto key = getExprKey (ctx, var->getInit ());
210232 assert (key && " expression rule has no key" );
@@ -215,7 +237,7 @@ std::vector<ExprKey> GetExprKeys(clang::ASTContext &ctx,
215237 if (auto construct =
216238 llvm::dyn_cast<clang::CXXUnresolvedConstructExpr>(returned)) {
217239 std::vector<ExprKey> keys;
218- for (auto type : resolveMemberType (construct->getTypeAsWritten ())) {
240+ for (auto type : resolveMemberType (sema, construct->getTypeAsWritten ())) {
219241 if (type->getAs <clang::TemplateTypeParmType>()) {
220242 if (!llvm::is_contained (keys, ExprKey{kAnyConstructor })) {
221243 keys.push_back (kAnyConstructor );
0 commit comments