@@ -48,6 +48,8 @@ class HeuristicResolverImpl {
4848 std::vector<const NamedDecl *>
4949 lookupDependentName (CXXRecordDecl *RD, DeclarationName Name,
5050 llvm::function_ref<bool (const NamedDecl *ND)> Filter);
51+ TagDecl *resolveTypeToTagDecl (QualType T);
52+ QualType simplifyType (QualType Type, const Expr *E, bool UnwrapPointer);
5153
5254private:
5355 ASTContext &Ctx;
@@ -73,20 +75,6 @@ class HeuristicResolverImpl {
7375 QualType resolveExprToType (const Expr *E);
7476 std::vector<const NamedDecl *> resolveExprToDecls (const Expr *E);
7577
76- // Helper function for HeuristicResolver::resolveDependentMember()
77- // which takes a possibly-dependent type `T` and heuristically
78- // resolves it to a TagDecl in which we can try name lookup.
79- TagDecl *resolveTypeToTagDecl (const Type *T);
80-
81- // Helper function for simplifying a type.
82- // `Type` is the type to simplify.
83- // `E` is the expression whose type `Type` is, if known. This sometimes
84- // contains information relevant to the type that's not stored in `Type`
85- // itself.
86- // If `UnwrapPointer` is true, exactly only pointer type will be unwrapped
87- // during simplification, and the operation fails if no pointer type is found.
88- QualType simplifyType (QualType Type, const Expr *E, bool UnwrapPointer);
89-
9078 bool findOrdinaryMemberInDependentClasses (const CXXBaseSpecifier *Specifier,
9179 CXXBasePath &Path,
9280 DeclarationName Name);
@@ -133,8 +121,10 @@ TemplateName getReferencedTemplateName(const Type *T) {
133121// Helper function for HeuristicResolver::resolveDependentMember()
134122// which takes a possibly-dependent type `T` and heuristically
135123// resolves it to a CXXRecordDecl in which we can try name lookup.
136- TagDecl *HeuristicResolverImpl::resolveTypeToTagDecl (const Type *T) {
137- assert (T);
124+ TagDecl *HeuristicResolverImpl::resolveTypeToTagDecl (QualType QT) {
125+ const Type *T = QT.getTypePtrOrNull ();
126+ if (!T)
127+ return nullptr ;
138128
139129 // Unwrap type sugar such as type aliases.
140130 T = T->getCanonicalTypeInternal ().getTypePtr ();
@@ -148,7 +138,15 @@ TagDecl *HeuristicResolverImpl::resolveTypeToTagDecl(const Type *T) {
148138 }
149139
150140 if (auto *TT = T->getAs <TagType>()) {
151- return TT->getDecl ();
141+ TagDecl *TD = TT->getDecl ();
142+ // Template might not be instantiated yet, fall back to primary template
143+ // in such cases.
144+ if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(TD)) {
145+ if (CTSD->getTemplateSpecializationKind () == TSK_Undeclared) {
146+ return CTSD->getSpecializedTemplate ()->getTemplatedDecl ();
147+ }
148+ }
149+ return TD;
152150 }
153151
154152 if (const auto *ICNT = T->getAs <InjectedClassNameType>())
@@ -330,8 +328,7 @@ HeuristicResolverImpl::resolveTypeOfCallExpr(const CallExpr *CE) {
330328 if (const auto *FnTypePtr = CalleeType->getAs <PointerType>())
331329 CalleeType = FnTypePtr->getPointeeType ();
332330 if (const FunctionType *FnType = CalleeType->getAs <FunctionType>()) {
333- if (const auto *D =
334- resolveTypeToTagDecl (FnType->getReturnType ().getTypePtr ())) {
331+ if (const auto *D = resolveTypeToTagDecl (FnType->getReturnType ())) {
335332 return {D};
336333 }
337334 }
@@ -442,7 +439,7 @@ bool findOrdinaryMember(const CXXRecordDecl *RD, CXXBasePath &Path,
442439bool HeuristicResolverImpl::findOrdinaryMemberInDependentClasses (
443440 const CXXBaseSpecifier *Specifier, CXXBasePath &Path,
444441 DeclarationName Name) {
445- TagDecl *TD = resolveTypeToTagDecl (Specifier->getType (). getTypePtr () );
442+ TagDecl *TD = resolveTypeToTagDecl (Specifier->getType ());
446443 if (const auto *RD = dyn_cast_if_present<CXXRecordDecl>(TD)) {
447444 return findOrdinaryMember (RD, Path, Name);
448445 }
@@ -485,10 +482,7 @@ std::vector<const NamedDecl *> HeuristicResolverImpl::lookupDependentName(
485482std::vector<const NamedDecl *> HeuristicResolverImpl::resolveDependentMember (
486483 QualType QT, DeclarationName Name,
487484 llvm::function_ref<bool (const NamedDecl *ND)> Filter) {
488- const Type *T = QT.getTypePtrOrNull ();
489- if (!T)
490- return {};
491- TagDecl *TD = resolveTypeToTagDecl (T);
485+ TagDecl *TD = resolveTypeToTagDecl (QT);
492486 if (!TD)
493487 return {};
494488 if (auto *ED = dyn_cast<EnumDecl>(TD)) {
@@ -555,5 +549,12 @@ std::vector<const NamedDecl *> HeuristicResolver::lookupDependentName(
555549const QualType HeuristicResolver::getPointeeType (QualType T) const {
556550 return HeuristicResolverImpl (Ctx).getPointeeType (T);
557551}
552+ TagDecl *HeuristicResolver::resolveTypeToTagDecl (QualType T) const {
553+ return HeuristicResolverImpl (Ctx).resolveTypeToTagDecl (T);
554+ }
555+ QualType HeuristicResolver::simplifyType (QualType Type, const Expr *E,
556+ bool UnwrapPointer) {
557+ return HeuristicResolverImpl (Ctx).simplifyType (Type, E, UnwrapPointer);
558+ }
558559
559560} // namespace clang
0 commit comments