[clang] [clang][CodeComplete] Use HeuristicResolver in getAsRecordDecl() (PR #130473)

2025-04-10 Thread Nathan Ridge via cfe-commits

https://github.com/HighCommander4 closed 
https://github.com/llvm/llvm-project/pull/130473
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][CodeComplete] Use HeuristicResolver in getAsRecordDecl() (PR #130473)

2025-04-10 Thread Nathan Ridge via cfe-commits

HighCommander4 wrote:

(Rebased)

https://github.com/llvm/llvm-project/pull/130473
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][CodeComplete] Use HeuristicResolver in getAsRecordDecl() (PR #130473)

2025-04-10 Thread Nathan Ridge via cfe-commits

https://github.com/HighCommander4 updated 
https://github.com/llvm/llvm-project/pull/130473

>From f6c57947b12d8c22e8e54757fc03ff1e407aa12e Mon Sep 17 00:00:00 2001
From: Nathan Ridge 
Date: Sun, 9 Mar 2025 01:36:25 -0500
Subject: [PATCH 1/6] Change the parameter type of resolveTypeToTagDecl() to
 QualType

---
 clang/lib/Sema/HeuristicResolver.cpp | 18 --
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/clang/lib/Sema/HeuristicResolver.cpp 
b/clang/lib/Sema/HeuristicResolver.cpp
index 4544d75ea73c4..a93b9d1ce8a64 100644
--- a/clang/lib/Sema/HeuristicResolver.cpp
+++ b/clang/lib/Sema/HeuristicResolver.cpp
@@ -76,7 +76,7 @@ class HeuristicResolverImpl {
   // Helper function for HeuristicResolver::resolveDependentMember()
   // which takes a possibly-dependent type `T` and heuristically
   // resolves it to a TagDecl in which we can try name lookup.
-  TagDecl *resolveTypeToTagDecl(const Type *T);
+  TagDecl *resolveTypeToTagDecl(QualType T);
 
   // Helper function for simplifying a type.
   // `Type` is the type to simplify.
@@ -133,8 +133,10 @@ TemplateName getReferencedTemplateName(const Type *T) {
 // Helper function for HeuristicResolver::resolveDependentMember()
 // which takes a possibly-dependent type `T` and heuristically
 // resolves it to a CXXRecordDecl in which we can try name lookup.
-TagDecl *HeuristicResolverImpl::resolveTypeToTagDecl(const Type *T) {
-  assert(T);
+TagDecl *HeuristicResolverImpl::resolveTypeToTagDecl(QualType QT) {
+  const Type *T = QT.getTypePtrOrNull();
+  if (!T)
+return nullptr;
 
   // Unwrap type sugar such as type aliases.
   T = T->getCanonicalTypeInternal().getTypePtr();
@@ -330,8 +332,7 @@ HeuristicResolverImpl::resolveTypeOfCallExpr(const CallExpr 
*CE) {
   if (const auto *FnTypePtr = CalleeType->getAs())
 CalleeType = FnTypePtr->getPointeeType();
   if (const FunctionType *FnType = CalleeType->getAs()) {
-if (const auto *D =
-resolveTypeToTagDecl(FnType->getReturnType().getTypePtr())) {
+if (const auto *D = resolveTypeToTagDecl(FnType->getReturnType())) {
   return {D};
 }
   }
@@ -442,7 +443,7 @@ bool findOrdinaryMember(const CXXRecordDecl *RD, 
CXXBasePath &Path,
 bool HeuristicResolverImpl::findOrdinaryMemberInDependentClasses(
 const CXXBaseSpecifier *Specifier, CXXBasePath &Path,
 DeclarationName Name) {
-  TagDecl *TD = resolveTypeToTagDecl(Specifier->getType().getTypePtr());
+  TagDecl *TD = resolveTypeToTagDecl(Specifier->getType());
   if (const auto *RD = dyn_cast_if_present(TD)) {
 return findOrdinaryMember(RD, Path, Name);
   }
@@ -485,10 +486,7 @@ std::vector 
HeuristicResolverImpl::lookupDependentName(
 std::vector HeuristicResolverImpl::resolveDependentMember(
 QualType QT, DeclarationName Name,
 llvm::function_ref Filter) {
-  const Type *T = QT.getTypePtrOrNull();
-  if (!T)
-return {};
-  TagDecl *TD = resolveTypeToTagDecl(T);
+  TagDecl *TD = resolveTypeToTagDecl(QT);
   if (!TD)
 return {};
   if (auto *ED = dyn_cast(TD)) {

>From a8b885fc950ad6dda24123027f98a9e77fed3785 Mon Sep 17 00:00:00 2001
From: Nathan Ridge 
Date: Sun, 9 Mar 2025 01:43:25 -0500
Subject: [PATCH 2/6] Expose resolveTypeToTagDecl() publically in
 HeuristicResolver

---
 clang/include/clang/Sema/HeuristicResolver.h | 4 
 clang/lib/Sema/HeuristicResolver.cpp | 9 -
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/clang/include/clang/Sema/HeuristicResolver.h 
b/clang/include/clang/Sema/HeuristicResolver.h
index f511815b40199..c971b9a6a7b51 100644
--- a/clang/include/clang/Sema/HeuristicResolver.h
+++ b/clang/include/clang/Sema/HeuristicResolver.h
@@ -81,6 +81,10 @@ class HeuristicResolver {
   // could look up the name appearing on the RHS.
   const QualType getPointeeType(QualType T) const;
 
+  // Heuristically resolve a possibly-dependent type `T` to a TagDecl
+  // in which a member's name can be looked up.
+  TagDecl *resolveTypeToTagDecl(QualType T) const;
+
 private:
   ASTContext &Ctx;
 };
diff --git a/clang/lib/Sema/HeuristicResolver.cpp 
b/clang/lib/Sema/HeuristicResolver.cpp
index a93b9d1ce8a64..c75ded526e29f 100644
--- a/clang/lib/Sema/HeuristicResolver.cpp
+++ b/clang/lib/Sema/HeuristicResolver.cpp
@@ -48,6 +48,7 @@ class HeuristicResolverImpl {
   std::vector
   lookupDependentName(CXXRecordDecl *RD, DeclarationName Name,
   llvm::function_ref Filter);
+  TagDecl *resolveTypeToTagDecl(QualType T);
 
 private:
   ASTContext &Ctx;
@@ -73,11 +74,6 @@ class HeuristicResolverImpl {
   QualType resolveExprToType(const Expr *E);
   std::vector resolveExprToDecls(const Expr *E);
 
-  // Helper function for HeuristicResolver::resolveDependentMember()
-  // which takes a possibly-dependent type `T` and heuristically
-  // resolves it to a TagDecl in which we can try name lookup.
-  TagDecl *resolveTypeToTagDecl(QualType T);
-
   // Helper function for simplifying a type.
   // `Type` is the type to simplify.
   // `E` is 

[clang] [clang][CodeComplete] Use HeuristicResolver in getAsRecordDecl() (PR #130473)

2025-04-10 Thread Nathan Ridge via cfe-commits


@@ -54,8 +54,9 @@ IdentifierInfo *Parser::getSEHExceptKeyword() {
 }
 
 Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies)
-: PP(pp), PreferredType(pp.isCodeCompletionEnabled()), Actions(actions),
-  Diags(PP.getDiagnostics()), StackHandler(Diags),
+: PP(pp),
+  PreferredType(&actions.getASTContext(), pp.isCodeCompletionEnabled()),

HighCommander4 wrote:

I actually tried this initially, but `PreferredTypeBuilder` has its assignment 
operator called 
[here](https://searchfox.org/llvm/rev/71f629fc2a93e41577c09bdd782b2ba524ed5fea/clang/include/clang/Parse/Parser.h#1061),
 and that does not compile if it has a member of reference type.

https://github.com/llvm/llvm-project/pull/130473
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][CodeComplete] Use HeuristicResolver in getAsRecordDecl() (PR #130473)

2025-04-10 Thread Younan Zhang via cfe-commits


@@ -5346,27 +5348,11 @@ AddRecordMembersCompletionResults(Sema &SemaRef, 
ResultBuilder &Results,
 // Returns the RecordDecl inside the BaseType, falling back to primary template
 // in case of specializations. Since we might not have a decl for the
 // instantiation/specialization yet, e.g. dependent code.
-static RecordDecl *getAsRecordDecl(QualType BaseType) {
-  BaseType = BaseType.getNonReferenceType();
-  if (auto *RD = BaseType->getAsRecordDecl()) {
-if (const auto *CTSD =
-llvm::dyn_cast(RD)) {
-  // Template might not be instantiated yet, fall back to primary template
-  // in such cases.
-  if (CTSD->getTemplateSpecializationKind() == TSK_Undeclared)
-RD = CTSD->getSpecializedTemplate()->getTemplatedDecl();
-}
-return RD;
-  }
-
-  if (const auto *TST = BaseType->getAs()) {
-if (const auto *TD = dyn_cast_or_null(
-TST->getTemplateName().getAsTemplateDecl())) {
-  return TD->getTemplatedDecl();
-}
-  }

zyn0217 wrote:

I might be missing something, do we now call 
`resolveTemplateSpecializationType` somewhere?

https://github.com/llvm/llvm-project/pull/130473
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][CodeComplete] Use HeuristicResolver in getAsRecordDecl() (PR #130473)

2025-04-10 Thread Younan Zhang via cfe-commits

https://github.com/zyn0217 edited 
https://github.com/llvm/llvm-project/pull/130473
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][CodeComplete] Use HeuristicResolver in getAsRecordDecl() (PR #130473)

2025-04-07 Thread Younan Zhang via cfe-commits

https://github.com/zyn0217 approved this pull request.


https://github.com/llvm/llvm-project/pull/130473
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][CodeComplete] Use HeuristicResolver in getAsRecordDecl() (PR #130473)

2025-04-07 Thread Younan Zhang via cfe-commits

https://github.com/zyn0217 commented:

Thanks for consistently working on this!

https://github.com/llvm/llvm-project/pull/130473
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][CodeComplete] Use HeuristicResolver in getAsRecordDecl() (PR #130473)

2025-04-07 Thread Younan Zhang via cfe-commits


@@ -5346,27 +5348,11 @@ AddRecordMembersCompletionResults(Sema &SemaRef, 
ResultBuilder &Results,
 // Returns the RecordDecl inside the BaseType, falling back to primary template
 // in case of specializations. Since we might not have a decl for the
 // instantiation/specialization yet, e.g. dependent code.
-static RecordDecl *getAsRecordDecl(QualType BaseType) {
-  BaseType = BaseType.getNonReferenceType();
-  if (auto *RD = BaseType->getAsRecordDecl()) {
-if (const auto *CTSD =
-llvm::dyn_cast(RD)) {
-  // Template might not be instantiated yet, fall back to primary template
-  // in such cases.
-  if (CTSD->getTemplateSpecializationKind() == TSK_Undeclared)
-RD = CTSD->getSpecializedTemplate()->getTemplatedDecl();
-}
-return RD;
-  }
-
-  if (const auto *TST = BaseType->getAs()) {
-if (const auto *TD = dyn_cast_or_null(
-TST->getTemplateName().getAsTemplateDecl())) {
-  return TD->getTemplatedDecl();
-}
-  }

zyn0217 wrote:

Oh nevermind it's inside resolveTypeToTagDecl

https://github.com/llvm/llvm-project/pull/130473
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][CodeComplete] Use HeuristicResolver in getAsRecordDecl() (PR #130473)

2025-04-07 Thread Younan Zhang via cfe-commits


@@ -54,8 +54,9 @@ IdentifierInfo *Parser::getSEHExceptKeyword() {
 }
 
 Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies)
-: PP(pp), PreferredType(pp.isCodeCompletionEnabled()), Actions(actions),
-  Diags(PP.getDiagnostics()), StackHandler(Diags),
+: PP(pp),
+  PreferredType(&actions.getASTContext(), pp.isCodeCompletionEnabled()),

zyn0217 wrote:

nit: I think we have a preference of using references than pointers if it is 
known to be non-null.

https://github.com/llvm/llvm-project/pull/130473
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][CodeComplete] Use HeuristicResolver in getAsRecordDecl() (PR #130473)

2025-04-07 Thread Nathan Ridge via cfe-commits

HighCommander4 wrote:

Review ping :)

https://github.com/llvm/llvm-project/pull/130473
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][CodeComplete] Use HeuristicResolver in getAsRecordDecl() (PR #130473)

2025-04-05 Thread Nathan Ridge via cfe-commits

HighCommander4 wrote:

(I messed things up a bit here by merging a PR that was stacked on top of this 
into this one. Marking as Draft until I sort that out.)

https://github.com/llvm/llvm-project/pull/130473
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][CodeComplete] Use HeuristicResolver in getAsRecordDecl() (PR #130473)

2025-04-05 Thread Nathan Ridge via cfe-commits

https://github.com/HighCommander4 ready_for_review 
https://github.com/llvm/llvm-project/pull/130473
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][CodeComplete] Use HeuristicResolver in getAsRecordDecl() (PR #130473)

2025-03-26 Thread Nathan Ridge via cfe-commits

https://github.com/HighCommander4 converted_to_draft 
https://github.com/llvm/llvm-project/pull/130473
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][CodeComplete] Use HeuristicResolver in getAsRecordDecl() (PR #130473)

2025-03-22 Thread Nathan Ridge via cfe-commits

HighCommander4 wrote:

(Rebased)

https://github.com/llvm/llvm-project/pull/130473
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][CodeComplete] Use HeuristicResolver in getAsRecordDecl() (PR #130473)

2025-03-22 Thread Nathan Ridge via cfe-commits

https://github.com/HighCommander4 updated 
https://github.com/llvm/llvm-project/pull/130473

>From ea2b2409894092ddc7b3fea5a6bee887e4d62235 Mon Sep 17 00:00:00 2001
From: Nathan Ridge 
Date: Sun, 9 Mar 2025 01:36:25 -0500
Subject: [PATCH 1/6] Change the parameter type of resolveTypeToTagDecl() to
 QualType

---
 clang/lib/Sema/HeuristicResolver.cpp | 18 --
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/clang/lib/Sema/HeuristicResolver.cpp 
b/clang/lib/Sema/HeuristicResolver.cpp
index 4544d75ea73c4..a93b9d1ce8a64 100644
--- a/clang/lib/Sema/HeuristicResolver.cpp
+++ b/clang/lib/Sema/HeuristicResolver.cpp
@@ -76,7 +76,7 @@ class HeuristicResolverImpl {
   // Helper function for HeuristicResolver::resolveDependentMember()
   // which takes a possibly-dependent type `T` and heuristically
   // resolves it to a TagDecl in which we can try name lookup.
-  TagDecl *resolveTypeToTagDecl(const Type *T);
+  TagDecl *resolveTypeToTagDecl(QualType T);
 
   // Helper function for simplifying a type.
   // `Type` is the type to simplify.
@@ -133,8 +133,10 @@ TemplateName getReferencedTemplateName(const Type *T) {
 // Helper function for HeuristicResolver::resolveDependentMember()
 // which takes a possibly-dependent type `T` and heuristically
 // resolves it to a CXXRecordDecl in which we can try name lookup.
-TagDecl *HeuristicResolverImpl::resolveTypeToTagDecl(const Type *T) {
-  assert(T);
+TagDecl *HeuristicResolverImpl::resolveTypeToTagDecl(QualType QT) {
+  const Type *T = QT.getTypePtrOrNull();
+  if (!T)
+return nullptr;
 
   // Unwrap type sugar such as type aliases.
   T = T->getCanonicalTypeInternal().getTypePtr();
@@ -330,8 +332,7 @@ HeuristicResolverImpl::resolveTypeOfCallExpr(const CallExpr 
*CE) {
   if (const auto *FnTypePtr = CalleeType->getAs())
 CalleeType = FnTypePtr->getPointeeType();
   if (const FunctionType *FnType = CalleeType->getAs()) {
-if (const auto *D =
-resolveTypeToTagDecl(FnType->getReturnType().getTypePtr())) {
+if (const auto *D = resolveTypeToTagDecl(FnType->getReturnType())) {
   return {D};
 }
   }
@@ -442,7 +443,7 @@ bool findOrdinaryMember(const CXXRecordDecl *RD, 
CXXBasePath &Path,
 bool HeuristicResolverImpl::findOrdinaryMemberInDependentClasses(
 const CXXBaseSpecifier *Specifier, CXXBasePath &Path,
 DeclarationName Name) {
-  TagDecl *TD = resolveTypeToTagDecl(Specifier->getType().getTypePtr());
+  TagDecl *TD = resolveTypeToTagDecl(Specifier->getType());
   if (const auto *RD = dyn_cast_if_present(TD)) {
 return findOrdinaryMember(RD, Path, Name);
   }
@@ -485,10 +486,7 @@ std::vector 
HeuristicResolverImpl::lookupDependentName(
 std::vector HeuristicResolverImpl::resolveDependentMember(
 QualType QT, DeclarationName Name,
 llvm::function_ref Filter) {
-  const Type *T = QT.getTypePtrOrNull();
-  if (!T)
-return {};
-  TagDecl *TD = resolveTypeToTagDecl(T);
+  TagDecl *TD = resolveTypeToTagDecl(QT);
   if (!TD)
 return {};
   if (auto *ED = dyn_cast(TD)) {

>From d49ea63cb81e1762dbb3292fedd2d1885f0c94f7 Mon Sep 17 00:00:00 2001
From: Nathan Ridge 
Date: Sun, 9 Mar 2025 01:43:25 -0500
Subject: [PATCH 2/6] Expose resolveTypeToTagDecl() publically in
 HeuristicResolver

---
 clang/include/clang/Sema/HeuristicResolver.h | 4 
 clang/lib/Sema/HeuristicResolver.cpp | 9 -
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/clang/include/clang/Sema/HeuristicResolver.h 
b/clang/include/clang/Sema/HeuristicResolver.h
index f511815b40199..c971b9a6a7b51 100644
--- a/clang/include/clang/Sema/HeuristicResolver.h
+++ b/clang/include/clang/Sema/HeuristicResolver.h
@@ -81,6 +81,10 @@ class HeuristicResolver {
   // could look up the name appearing on the RHS.
   const QualType getPointeeType(QualType T) const;
 
+  // Heuristically resolve a possibly-dependent type `T` to a TagDecl
+  // in which a member's name can be looked up.
+  TagDecl *resolveTypeToTagDecl(QualType T) const;
+
 private:
   ASTContext &Ctx;
 };
diff --git a/clang/lib/Sema/HeuristicResolver.cpp 
b/clang/lib/Sema/HeuristicResolver.cpp
index a93b9d1ce8a64..c75ded526e29f 100644
--- a/clang/lib/Sema/HeuristicResolver.cpp
+++ b/clang/lib/Sema/HeuristicResolver.cpp
@@ -48,6 +48,7 @@ class HeuristicResolverImpl {
   std::vector
   lookupDependentName(CXXRecordDecl *RD, DeclarationName Name,
   llvm::function_ref Filter);
+  TagDecl *resolveTypeToTagDecl(QualType T);
 
 private:
   ASTContext &Ctx;
@@ -73,11 +74,6 @@ class HeuristicResolverImpl {
   QualType resolveExprToType(const Expr *E);
   std::vector resolveExprToDecls(const Expr *E);
 
-  // Helper function for HeuristicResolver::resolveDependentMember()
-  // which takes a possibly-dependent type `T` and heuristically
-  // resolves it to a TagDecl in which we can try name lookup.
-  TagDecl *resolveTypeToTagDecl(QualType T);
-
   // Helper function for simplifying a type.
   // `Type` is the type to simplify.
   // `E` is 

[clang] [clang][CodeComplete] Use HeuristicResolver in getAsRecordDecl() (PR #130473)

2025-03-21 Thread Nathan Ridge via cfe-commits

https://github.com/HighCommander4 updated 
https://github.com/llvm/llvm-project/pull/130473

>From 909de4a22dcda164b8fcb539e0907a77f99b3b00 Mon Sep 17 00:00:00 2001
From: Nathan Ridge 
Date: Sun, 9 Mar 2025 01:36:25 -0500
Subject: [PATCH 1/6] Change the parameter type of resolveTypeToTagDecl() to
 QualType

---
 clang/lib/Sema/HeuristicResolver.cpp | 18 --
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/clang/lib/Sema/HeuristicResolver.cpp 
b/clang/lib/Sema/HeuristicResolver.cpp
index 7aecd2a73b539..3c7918165ee42 100644
--- a/clang/lib/Sema/HeuristicResolver.cpp
+++ b/clang/lib/Sema/HeuristicResolver.cpp
@@ -75,7 +75,7 @@ class HeuristicResolverImpl {
   // Helper function for HeuristicResolver::resolveDependentMember()
   // which takes a possibly-dependent type `T` and heuristically
   // resolves it to a TagDecl in which we can try name lookup.
-  TagDecl *resolveTypeToTagDecl(const Type *T);
+  TagDecl *resolveTypeToTagDecl(QualType T);
 
   // Helper function for simplifying a type.
   // `Type` is the type to simplify.
@@ -132,8 +132,10 @@ TemplateName getReferencedTemplateName(const Type *T) {
 // Helper function for HeuristicResolver::resolveDependentMember()
 // which takes a possibly-dependent type `T` and heuristically
 // resolves it to a CXXRecordDecl in which we can try name lookup.
-TagDecl *HeuristicResolverImpl::resolveTypeToTagDecl(const Type *T) {
-  assert(T);
+TagDecl *HeuristicResolverImpl::resolveTypeToTagDecl(QualType QT) {
+  const Type *T = QT.getTypePtrOrNull();
+  if (!T)
+return nullptr;
 
   // Unwrap type sugar such as type aliases.
   T = T->getCanonicalTypeInternal().getTypePtr();
@@ -315,8 +317,7 @@ HeuristicResolverImpl::resolveTypeOfCallExpr(const CallExpr 
*CE) {
   if (const auto *FnTypePtr = CalleeType->getAs())
 CalleeType = FnTypePtr->getPointeeType();
   if (const FunctionType *FnType = CalleeType->getAs()) {
-if (const auto *D =
-resolveTypeToTagDecl(FnType->getReturnType().getTypePtr())) {
+if (const auto *D = resolveTypeToTagDecl(FnType->getReturnType())) {
   return {D};
 }
   }
@@ -427,7 +428,7 @@ bool findOrdinaryMember(const CXXRecordDecl *RD, 
CXXBasePath &Path,
 bool HeuristicResolverImpl::findOrdinaryMemberInDependentClasses(
 const CXXBaseSpecifier *Specifier, CXXBasePath &Path,
 DeclarationName Name) {
-  TagDecl *TD = resolveTypeToTagDecl(Specifier->getType().getTypePtr());
+  TagDecl *TD = resolveTypeToTagDecl(Specifier->getType());
   if (const auto *RD = dyn_cast_if_present(TD)) {
 return findOrdinaryMember(RD, Path, Name);
   }
@@ -470,10 +471,7 @@ std::vector 
HeuristicResolverImpl::lookupDependentName(
 std::vector HeuristicResolverImpl::resolveDependentMember(
 QualType QT, DeclarationName Name,
 llvm::function_ref Filter) {
-  const Type *T = QT.getTypePtrOrNull();
-  if (!T)
-return {};
-  TagDecl *TD = resolveTypeToTagDecl(T);
+  TagDecl *TD = resolveTypeToTagDecl(QT);
   if (!TD)
 return {};
   if (auto *ED = dyn_cast(TD)) {

>From d5be29e9f997ae707aff3d5d5c5255d3b87af9a2 Mon Sep 17 00:00:00 2001
From: Nathan Ridge 
Date: Sun, 9 Mar 2025 01:43:25 -0500
Subject: [PATCH 2/6] Expose resolveTypeToTagDecl() publically in
 HeuristicResolver

---
 clang/include/clang/Sema/HeuristicResolver.h | 4 
 clang/lib/Sema/HeuristicResolver.cpp | 9 -
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/clang/include/clang/Sema/HeuristicResolver.h 
b/clang/include/clang/Sema/HeuristicResolver.h
index f511815b40199..c971b9a6a7b51 100644
--- a/clang/include/clang/Sema/HeuristicResolver.h
+++ b/clang/include/clang/Sema/HeuristicResolver.h
@@ -81,6 +81,10 @@ class HeuristicResolver {
   // could look up the name appearing on the RHS.
   const QualType getPointeeType(QualType T) const;
 
+  // Heuristically resolve a possibly-dependent type `T` to a TagDecl
+  // in which a member's name can be looked up.
+  TagDecl *resolveTypeToTagDecl(QualType T) const;
+
 private:
   ASTContext &Ctx;
 };
diff --git a/clang/lib/Sema/HeuristicResolver.cpp 
b/clang/lib/Sema/HeuristicResolver.cpp
index 3c7918165ee42..11fe786fa91c6 100644
--- a/clang/lib/Sema/HeuristicResolver.cpp
+++ b/clang/lib/Sema/HeuristicResolver.cpp
@@ -47,6 +47,7 @@ class HeuristicResolverImpl {
   std::vector
   lookupDependentName(CXXRecordDecl *RD, DeclarationName Name,
   llvm::function_ref Filter);
+  TagDecl *resolveTypeToTagDecl(QualType T);
 
 private:
   ASTContext &Ctx;
@@ -72,11 +73,6 @@ class HeuristicResolverImpl {
   QualType resolveExprToType(const Expr *E);
   std::vector resolveExprToDecls(const Expr *E);
 
-  // Helper function for HeuristicResolver::resolveDependentMember()
-  // which takes a possibly-dependent type `T` and heuristically
-  // resolves it to a TagDecl in which we can try name lookup.
-  TagDecl *resolveTypeToTagDecl(QualType T);
-
   // Helper function for simplifying a type.
   // `Type` is the type to simplify.
   // `E` is 

[clang] [clang][CodeComplete] Use HeuristicResolver in getAsRecordDecl() (PR #130473)

2025-03-21 Thread Nathan Ridge via cfe-commits

HighCommander4 wrote:

Fixed now. Resubmitting for review.

https://github.com/llvm/llvm-project/pull/130473
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][CodeComplete] Use HeuristicResolver in getAsRecordDecl() (PR #130473)

2025-03-21 Thread Nathan Ridge via cfe-commits

https://github.com/HighCommander4 updated 
https://github.com/llvm/llvm-project/pull/130473

>From 66e5ed1f1fcfe5a52d110ae228ddd51bd487ee16 Mon Sep 17 00:00:00 2001
From: Nathan Ridge 
Date: Sun, 9 Mar 2025 01:36:25 -0500
Subject: [PATCH 1/7] Change the parameter type of resolveTypeToTagDecl() to
 QualType

---
 clang/lib/Sema/HeuristicResolver.cpp | 18 --
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/clang/lib/Sema/HeuristicResolver.cpp 
b/clang/lib/Sema/HeuristicResolver.cpp
index 7aecd2a73b539..3c7918165ee42 100644
--- a/clang/lib/Sema/HeuristicResolver.cpp
+++ b/clang/lib/Sema/HeuristicResolver.cpp
@@ -75,7 +75,7 @@ class HeuristicResolverImpl {
   // Helper function for HeuristicResolver::resolveDependentMember()
   // which takes a possibly-dependent type `T` and heuristically
   // resolves it to a TagDecl in which we can try name lookup.
-  TagDecl *resolveTypeToTagDecl(const Type *T);
+  TagDecl *resolveTypeToTagDecl(QualType T);
 
   // Helper function for simplifying a type.
   // `Type` is the type to simplify.
@@ -132,8 +132,10 @@ TemplateName getReferencedTemplateName(const Type *T) {
 // Helper function for HeuristicResolver::resolveDependentMember()
 // which takes a possibly-dependent type `T` and heuristically
 // resolves it to a CXXRecordDecl in which we can try name lookup.
-TagDecl *HeuristicResolverImpl::resolveTypeToTagDecl(const Type *T) {
-  assert(T);
+TagDecl *HeuristicResolverImpl::resolveTypeToTagDecl(QualType QT) {
+  const Type *T = QT.getTypePtrOrNull();
+  if (!T)
+return nullptr;
 
   // Unwrap type sugar such as type aliases.
   T = T->getCanonicalTypeInternal().getTypePtr();
@@ -315,8 +317,7 @@ HeuristicResolverImpl::resolveTypeOfCallExpr(const CallExpr 
*CE) {
   if (const auto *FnTypePtr = CalleeType->getAs())
 CalleeType = FnTypePtr->getPointeeType();
   if (const FunctionType *FnType = CalleeType->getAs()) {
-if (const auto *D =
-resolveTypeToTagDecl(FnType->getReturnType().getTypePtr())) {
+if (const auto *D = resolveTypeToTagDecl(FnType->getReturnType())) {
   return {D};
 }
   }
@@ -427,7 +428,7 @@ bool findOrdinaryMember(const CXXRecordDecl *RD, 
CXXBasePath &Path,
 bool HeuristicResolverImpl::findOrdinaryMemberInDependentClasses(
 const CXXBaseSpecifier *Specifier, CXXBasePath &Path,
 DeclarationName Name) {
-  TagDecl *TD = resolveTypeToTagDecl(Specifier->getType().getTypePtr());
+  TagDecl *TD = resolveTypeToTagDecl(Specifier->getType());
   if (const auto *RD = dyn_cast_if_present(TD)) {
 return findOrdinaryMember(RD, Path, Name);
   }
@@ -470,10 +471,7 @@ std::vector 
HeuristicResolverImpl::lookupDependentName(
 std::vector HeuristicResolverImpl::resolveDependentMember(
 QualType QT, DeclarationName Name,
 llvm::function_ref Filter) {
-  const Type *T = QT.getTypePtrOrNull();
-  if (!T)
-return {};
-  TagDecl *TD = resolveTypeToTagDecl(T);
+  TagDecl *TD = resolveTypeToTagDecl(QT);
   if (!TD)
 return {};
   if (auto *ED = dyn_cast(TD)) {

>From efa9503da4dcef74003f08493eb48c3d119cba0f Mon Sep 17 00:00:00 2001
From: Nathan Ridge 
Date: Sun, 9 Mar 2025 01:43:25 -0500
Subject: [PATCH 2/7] Expose resolveTypeToTagDecl() publically in
 HeuristicResolver

---
 clang/include/clang/Sema/HeuristicResolver.h | 4 
 clang/lib/Sema/HeuristicResolver.cpp | 9 -
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/clang/include/clang/Sema/HeuristicResolver.h 
b/clang/include/clang/Sema/HeuristicResolver.h
index f511815b40199..c971b9a6a7b51 100644
--- a/clang/include/clang/Sema/HeuristicResolver.h
+++ b/clang/include/clang/Sema/HeuristicResolver.h
@@ -81,6 +81,10 @@ class HeuristicResolver {
   // could look up the name appearing on the RHS.
   const QualType getPointeeType(QualType T) const;
 
+  // Heuristically resolve a possibly-dependent type `T` to a TagDecl
+  // in which a member's name can be looked up.
+  TagDecl *resolveTypeToTagDecl(QualType T) const;
+
 private:
   ASTContext &Ctx;
 };
diff --git a/clang/lib/Sema/HeuristicResolver.cpp 
b/clang/lib/Sema/HeuristicResolver.cpp
index 3c7918165ee42..11fe786fa91c6 100644
--- a/clang/lib/Sema/HeuristicResolver.cpp
+++ b/clang/lib/Sema/HeuristicResolver.cpp
@@ -47,6 +47,7 @@ class HeuristicResolverImpl {
   std::vector
   lookupDependentName(CXXRecordDecl *RD, DeclarationName Name,
   llvm::function_ref Filter);
+  TagDecl *resolveTypeToTagDecl(QualType T);
 
 private:
   ASTContext &Ctx;
@@ -72,11 +73,6 @@ class HeuristicResolverImpl {
   QualType resolveExprToType(const Expr *E);
   std::vector resolveExprToDecls(const Expr *E);
 
-  // Helper function for HeuristicResolver::resolveDependentMember()
-  // which takes a possibly-dependent type `T` and heuristically
-  // resolves it to a TagDecl in which we can try name lookup.
-  TagDecl *resolveTypeToTagDecl(QualType T);
-
   // Helper function for simplifying a type.
   // `Type` is the type to simplify.
   // `E` is 

[clang] [clang][CodeComplete] Use HeuristicResolver in getAsRecordDecl() (PR #130473)

2025-03-15 Thread Nathan Ridge via cfe-commits

https://github.com/HighCommander4 ready_for_review 
https://github.com/llvm/llvm-project/pull/130473
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][CodeComplete] Use HeuristicResolver in getAsRecordDecl() (PR #130473)

2025-03-09 Thread Nathan Ridge via cfe-commits

HighCommander4 wrote:

I split the PR up into a few commits for easier reviewing.

The high-level idea here is that the helper function `getAsRecordDecl()` in 
SemaCodeComplete.cpp is doing similar things to HeuristicResolver 
(specifically, `simplifyType` and `resolveTypeToRecordDecl`), but 
HeuristicResolver is handling a few more cases, and to get code completion to 
benefit from those cases the patch gets the helper function to use 
HeuristicResolver.

There was one case, `TSK_Undeclared`, that `getAsRecordDecl()` handled but 
HeuristicResolver didn't. I contemplated adding a standalone test case for that 
to HeuristicResolverTests but it's not easy because the situation only arises 
during code completion when the AST is not fully built. The case does have test 
coverage, in `clang/test/CodeCompletion/desig-init.cpp` (this test fails 
without the `TSK_Undeclared` handling).

https://github.com/llvm/llvm-project/pull/130473
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][CodeComplete] Use HeuristicResolver in getAsRecordDecl() (PR #130473)

2025-03-09 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Nathan Ridge (HighCommander4)


Changes

Fixes https://github.com/llvm/llvm-project/issues/130468

---
Full diff: https://github.com/llvm/llvm-project/pull/130473.diff


6 Files Affected:

- (modified) clang/include/clang/Sema/HeuristicResolver.h (+12) 
- (modified) clang/include/clang/Sema/Sema.h (+3-1) 
- (modified) clang/lib/Parse/Parser.cpp (+3-2) 
- (modified) clang/lib/Sema/HeuristicResolver.cpp (+25-24) 
- (modified) clang/lib/Sema/SemaCodeComplete.cpp (+15-28) 
- (modified) clang/test/CodeCompletion/member-access.cpp (+4-2) 


``diff
diff --git a/clang/include/clang/Sema/HeuristicResolver.h 
b/clang/include/clang/Sema/HeuristicResolver.h
index f511815b40199..df60d3359c6a6 100644
--- a/clang/include/clang/Sema/HeuristicResolver.h
+++ b/clang/include/clang/Sema/HeuristicResolver.h
@@ -81,6 +81,18 @@ class HeuristicResolver {
   // could look up the name appearing on the RHS.
   const QualType getPointeeType(QualType T) const;
 
+  // Heuristically resolve a possibly-dependent type `T` to a TagDecl
+  // in which a member's name can be looked up.
+  TagDecl *resolveTypeToTagDecl(QualType T) const;
+
+  // Simplify the type `Type`.
+  // `E` is the expression whose type `Type` is, if known. This sometimes
+  // contains information relevant to the type that's not stored in `Type`
+  // itself.
+  // If `UnwrapPointer` is true, exactly only pointer type will be unwrapped
+  // during simplification, and the operation fails if no pointer type is 
found.
+  QualType simplifyType(QualType Type, const Expr *E, bool UnwrapPointer);
+
 private:
   ASTContext &Ctx;
 };
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index fdef57e84ee3d..89ce852b0a09f 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -290,7 +290,8 @@ class FileNullabilityMap {
 /// parameter. This avoids updating the type on hot paths in the parser.
 class PreferredTypeBuilder {
 public:
-  PreferredTypeBuilder(bool Enabled) : Enabled(Enabled) {}
+  PreferredTypeBuilder(ASTContext *Ctx, bool Enabled)
+  : Ctx(Ctx), Enabled(Enabled) {}
 
   void enterCondition(Sema &S, SourceLocation Tok);
   void enterReturn(Sema &S, SourceLocation Tok);
@@ -336,6 +337,7 @@ class PreferredTypeBuilder {
   }
 
 private:
+  ASTContext *Ctx;
   bool Enabled;
   /// Start position of a token for which we store expected type.
   SourceLocation ExpectedLoc;
diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index 0710542f5e938..09e784a8e04de 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -52,8 +52,9 @@ IdentifierInfo *Parser::getSEHExceptKeyword() {
 }
 
 Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies)
-: PP(pp), PreferredType(pp.isCodeCompletionEnabled()), Actions(actions),
-  Diags(PP.getDiagnostics()), GreaterThanIsOperator(true),
+: PP(pp),
+  PreferredType(&actions.getASTContext(), pp.isCodeCompletionEnabled()),
+  Actions(actions), Diags(PP.getDiagnostics()), 
GreaterThanIsOperator(true),
   ColonIsSacred(false), InMessageExpression(false),
   TemplateParameterDepth(0), ParsingInObjCContainer(false) {
   SkipFunctionBodies = pp.isCodeCompletionEnabled() || skipFunctionBodies;
diff --git a/clang/lib/Sema/HeuristicResolver.cpp 
b/clang/lib/Sema/HeuristicResolver.cpp
index 7aecd2a73b539..d377379c627db 100644
--- a/clang/lib/Sema/HeuristicResolver.cpp
+++ b/clang/lib/Sema/HeuristicResolver.cpp
@@ -47,6 +47,8 @@ class HeuristicResolverImpl {
   std::vector
   lookupDependentName(CXXRecordDecl *RD, DeclarationName Name,
   llvm::function_ref Filter);
+  TagDecl *resolveTypeToTagDecl(QualType T);
+  QualType simplifyType(QualType Type, const Expr *E, bool UnwrapPointer);
 
 private:
   ASTContext &Ctx;
@@ -72,20 +74,6 @@ class HeuristicResolverImpl {
   QualType resolveExprToType(const Expr *E);
   std::vector resolveExprToDecls(const Expr *E);
 
-  // Helper function for HeuristicResolver::resolveDependentMember()
-  // which takes a possibly-dependent type `T` and heuristically
-  // resolves it to a TagDecl in which we can try name lookup.
-  TagDecl *resolveTypeToTagDecl(const Type *T);
-
-  // Helper function for simplifying a type.
-  // `Type` is the type to simplify.
-  // `E` is the expression whose type `Type` is, if known. This sometimes
-  // contains information relevant to the type that's not stored in `Type`
-  // itself.
-  // If `UnwrapPointer` is true, exactly only pointer type will be unwrapped
-  // during simplification, and the operation fails if no pointer type is 
found.
-  QualType simplifyType(QualType Type, const Expr *E, bool UnwrapPointer);
-
   bool findOrdinaryMemberInDependentClasses(const CXXBaseSpecifier *Specifier,
 CXXBasePath &Path,
 DeclarationName Name);
@@ -132,8 +120,10 @@ TemplateName getRe

[clang] [clang][CodeComplete] Use HeuristicResolver in getAsRecordDecl() (PR #130473)

2025-03-09 Thread Nathan Ridge via cfe-commits

https://github.com/HighCommander4 updated 
https://github.com/llvm/llvm-project/pull/130473

>From 66e5ed1f1fcfe5a52d110ae228ddd51bd487ee16 Mon Sep 17 00:00:00 2001
From: Nathan Ridge 
Date: Sun, 9 Mar 2025 01:36:25 -0500
Subject: [PATCH 1/6] Change the parameter type of resolveTypeToTagDecl() to
 QualType

---
 clang/lib/Sema/HeuristicResolver.cpp | 18 --
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/clang/lib/Sema/HeuristicResolver.cpp 
b/clang/lib/Sema/HeuristicResolver.cpp
index 7aecd2a73b539..3c7918165ee42 100644
--- a/clang/lib/Sema/HeuristicResolver.cpp
+++ b/clang/lib/Sema/HeuristicResolver.cpp
@@ -75,7 +75,7 @@ class HeuristicResolverImpl {
   // Helper function for HeuristicResolver::resolveDependentMember()
   // which takes a possibly-dependent type `T` and heuristically
   // resolves it to a TagDecl in which we can try name lookup.
-  TagDecl *resolveTypeToTagDecl(const Type *T);
+  TagDecl *resolveTypeToTagDecl(QualType T);
 
   // Helper function for simplifying a type.
   // `Type` is the type to simplify.
@@ -132,8 +132,10 @@ TemplateName getReferencedTemplateName(const Type *T) {
 // Helper function for HeuristicResolver::resolveDependentMember()
 // which takes a possibly-dependent type `T` and heuristically
 // resolves it to a CXXRecordDecl in which we can try name lookup.
-TagDecl *HeuristicResolverImpl::resolveTypeToTagDecl(const Type *T) {
-  assert(T);
+TagDecl *HeuristicResolverImpl::resolveTypeToTagDecl(QualType QT) {
+  const Type *T = QT.getTypePtrOrNull();
+  if (!T)
+return nullptr;
 
   // Unwrap type sugar such as type aliases.
   T = T->getCanonicalTypeInternal().getTypePtr();
@@ -315,8 +317,7 @@ HeuristicResolverImpl::resolveTypeOfCallExpr(const CallExpr 
*CE) {
   if (const auto *FnTypePtr = CalleeType->getAs())
 CalleeType = FnTypePtr->getPointeeType();
   if (const FunctionType *FnType = CalleeType->getAs()) {
-if (const auto *D =
-resolveTypeToTagDecl(FnType->getReturnType().getTypePtr())) {
+if (const auto *D = resolveTypeToTagDecl(FnType->getReturnType())) {
   return {D};
 }
   }
@@ -427,7 +428,7 @@ bool findOrdinaryMember(const CXXRecordDecl *RD, 
CXXBasePath &Path,
 bool HeuristicResolverImpl::findOrdinaryMemberInDependentClasses(
 const CXXBaseSpecifier *Specifier, CXXBasePath &Path,
 DeclarationName Name) {
-  TagDecl *TD = resolveTypeToTagDecl(Specifier->getType().getTypePtr());
+  TagDecl *TD = resolveTypeToTagDecl(Specifier->getType());
   if (const auto *RD = dyn_cast_if_present(TD)) {
 return findOrdinaryMember(RD, Path, Name);
   }
@@ -470,10 +471,7 @@ std::vector 
HeuristicResolverImpl::lookupDependentName(
 std::vector HeuristicResolverImpl::resolveDependentMember(
 QualType QT, DeclarationName Name,
 llvm::function_ref Filter) {
-  const Type *T = QT.getTypePtrOrNull();
-  if (!T)
-return {};
-  TagDecl *TD = resolveTypeToTagDecl(T);
+  TagDecl *TD = resolveTypeToTagDecl(QT);
   if (!TD)
 return {};
   if (auto *ED = dyn_cast(TD)) {

>From efa9503da4dcef74003f08493eb48c3d119cba0f Mon Sep 17 00:00:00 2001
From: Nathan Ridge 
Date: Sun, 9 Mar 2025 01:43:25 -0500
Subject: [PATCH 2/6] Expose resolveTypeToTagDecl() publically in
 HeuristicResolver

---
 clang/include/clang/Sema/HeuristicResolver.h | 4 
 clang/lib/Sema/HeuristicResolver.cpp | 9 -
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/clang/include/clang/Sema/HeuristicResolver.h 
b/clang/include/clang/Sema/HeuristicResolver.h
index f511815b40199..c971b9a6a7b51 100644
--- a/clang/include/clang/Sema/HeuristicResolver.h
+++ b/clang/include/clang/Sema/HeuristicResolver.h
@@ -81,6 +81,10 @@ class HeuristicResolver {
   // could look up the name appearing on the RHS.
   const QualType getPointeeType(QualType T) const;
 
+  // Heuristically resolve a possibly-dependent type `T` to a TagDecl
+  // in which a member's name can be looked up.
+  TagDecl *resolveTypeToTagDecl(QualType T) const;
+
 private:
   ASTContext &Ctx;
 };
diff --git a/clang/lib/Sema/HeuristicResolver.cpp 
b/clang/lib/Sema/HeuristicResolver.cpp
index 3c7918165ee42..11fe786fa91c6 100644
--- a/clang/lib/Sema/HeuristicResolver.cpp
+++ b/clang/lib/Sema/HeuristicResolver.cpp
@@ -47,6 +47,7 @@ class HeuristicResolverImpl {
   std::vector
   lookupDependentName(CXXRecordDecl *RD, DeclarationName Name,
   llvm::function_ref Filter);
+  TagDecl *resolveTypeToTagDecl(QualType T);
 
 private:
   ASTContext &Ctx;
@@ -72,11 +73,6 @@ class HeuristicResolverImpl {
   QualType resolveExprToType(const Expr *E);
   std::vector resolveExprToDecls(const Expr *E);
 
-  // Helper function for HeuristicResolver::resolveDependentMember()
-  // which takes a possibly-dependent type `T` and heuristically
-  // resolves it to a TagDecl in which we can try name lookup.
-  TagDecl *resolveTypeToTagDecl(QualType T);
-
   // Helper function for simplifying a type.
   // `Type` is the type to simplify.
   // `E` is 

[clang] [clang][CodeComplete] Use HeuristicResolver in getAsRecordDecl() (PR #130473)

2025-03-08 Thread Nathan Ridge via cfe-commits

https://github.com/HighCommander4 created 
https://github.com/llvm/llvm-project/pull/130473

Fixes https://github.com/llvm/llvm-project/issues/130468

>From 0999f2fb15b6703fc9f5c4ba5c9e21c14a90b4ed Mon Sep 17 00:00:00 2001
From: Nathan Ridge 
Date: Sun, 9 Mar 2025 01:36:25 -0500
Subject: [PATCH 1/4] Change the parameter type of resolveTypeToTagDecl() to
 QualType

---
 clang/lib/Sema/HeuristicResolver.cpp | 18 --
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/clang/lib/Sema/HeuristicResolver.cpp 
b/clang/lib/Sema/HeuristicResolver.cpp
index 7aecd2a73b539..3c7918165ee42 100644
--- a/clang/lib/Sema/HeuristicResolver.cpp
+++ b/clang/lib/Sema/HeuristicResolver.cpp
@@ -75,7 +75,7 @@ class HeuristicResolverImpl {
   // Helper function for HeuristicResolver::resolveDependentMember()
   // which takes a possibly-dependent type `T` and heuristically
   // resolves it to a TagDecl in which we can try name lookup.
-  TagDecl *resolveTypeToTagDecl(const Type *T);
+  TagDecl *resolveTypeToTagDecl(QualType T);
 
   // Helper function for simplifying a type.
   // `Type` is the type to simplify.
@@ -132,8 +132,10 @@ TemplateName getReferencedTemplateName(const Type *T) {
 // Helper function for HeuristicResolver::resolveDependentMember()
 // which takes a possibly-dependent type `T` and heuristically
 // resolves it to a CXXRecordDecl in which we can try name lookup.
-TagDecl *HeuristicResolverImpl::resolveTypeToTagDecl(const Type *T) {
-  assert(T);
+TagDecl *HeuristicResolverImpl::resolveTypeToTagDecl(QualType QT) {
+  const Type *T = QT.getTypePtrOrNull();
+  if (!T)
+return nullptr;
 
   // Unwrap type sugar such as type aliases.
   T = T->getCanonicalTypeInternal().getTypePtr();
@@ -315,8 +317,7 @@ HeuristicResolverImpl::resolveTypeOfCallExpr(const CallExpr 
*CE) {
   if (const auto *FnTypePtr = CalleeType->getAs())
 CalleeType = FnTypePtr->getPointeeType();
   if (const FunctionType *FnType = CalleeType->getAs()) {
-if (const auto *D =
-resolveTypeToTagDecl(FnType->getReturnType().getTypePtr())) {
+if (const auto *D = resolveTypeToTagDecl(FnType->getReturnType())) {
   return {D};
 }
   }
@@ -427,7 +428,7 @@ bool findOrdinaryMember(const CXXRecordDecl *RD, 
CXXBasePath &Path,
 bool HeuristicResolverImpl::findOrdinaryMemberInDependentClasses(
 const CXXBaseSpecifier *Specifier, CXXBasePath &Path,
 DeclarationName Name) {
-  TagDecl *TD = resolveTypeToTagDecl(Specifier->getType().getTypePtr());
+  TagDecl *TD = resolveTypeToTagDecl(Specifier->getType());
   if (const auto *RD = dyn_cast_if_present(TD)) {
 return findOrdinaryMember(RD, Path, Name);
   }
@@ -470,10 +471,7 @@ std::vector 
HeuristicResolverImpl::lookupDependentName(
 std::vector HeuristicResolverImpl::resolveDependentMember(
 QualType QT, DeclarationName Name,
 llvm::function_ref Filter) {
-  const Type *T = QT.getTypePtrOrNull();
-  if (!T)
-return {};
-  TagDecl *TD = resolveTypeToTagDecl(T);
+  TagDecl *TD = resolveTypeToTagDecl(QT);
   if (!TD)
 return {};
   if (auto *ED = dyn_cast(TD)) {

>From a3c77212039245d9f4704567fd426f36a29e947f Mon Sep 17 00:00:00 2001
From: Nathan Ridge 
Date: Sun, 9 Mar 2025 01:43:25 -0500
Subject: [PATCH 2/4] Expose resolveTypeToTagDecl() publically in
 HeuristicResolver

---
 clang/include/clang/Sema/HeuristicResolver.h | 4 
 clang/lib/Sema/HeuristicResolver.cpp | 9 -
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/clang/include/clang/Sema/HeuristicResolver.h 
b/clang/include/clang/Sema/HeuristicResolver.h
index f511815b40199..c971b9a6a7b51 100644
--- a/clang/include/clang/Sema/HeuristicResolver.h
+++ b/clang/include/clang/Sema/HeuristicResolver.h
@@ -81,6 +81,10 @@ class HeuristicResolver {
   // could look up the name appearing on the RHS.
   const QualType getPointeeType(QualType T) const;
 
+  // Heuristically resolve a possibly-dependent type `T` to a TagDecl
+  // in which a member's name can be looked up.
+  TagDecl *resolveTypeToTagDecl(QualType T) const;
+
 private:
   ASTContext &Ctx;
 };
diff --git a/clang/lib/Sema/HeuristicResolver.cpp 
b/clang/lib/Sema/HeuristicResolver.cpp
index 3c7918165ee42..11fe786fa91c6 100644
--- a/clang/lib/Sema/HeuristicResolver.cpp
+++ b/clang/lib/Sema/HeuristicResolver.cpp
@@ -47,6 +47,7 @@ class HeuristicResolverImpl {
   std::vector
   lookupDependentName(CXXRecordDecl *RD, DeclarationName Name,
   llvm::function_ref Filter);
+  TagDecl *resolveTypeToTagDecl(QualType T);
 
 private:
   ASTContext &Ctx;
@@ -72,11 +73,6 @@ class HeuristicResolverImpl {
   QualType resolveExprToType(const Expr *E);
   std::vector resolveExprToDecls(const Expr *E);
 
-  // Helper function for HeuristicResolver::resolveDependentMember()
-  // which takes a possibly-dependent type `T` and heuristically
-  // resolves it to a TagDecl in which we can try name lookup.
-  TagDecl *resolveTypeToTagDecl(QualType T);
-
   // Helper function for simplifying a