Skip to content

[clang][Sema] Handle pointer and reference type more robustly in HeuristicResolver::resolveMemberExpr() #124451

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 30, 2025

Conversation

HighCommander4
Copy link
Collaborator

@HighCommander4 HighCommander4 commented Jan 26, 2025

Fixes #124450

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Jan 26, 2025
@llvmbot
Copy link
Member

llvmbot commented Jan 26, 2025

@llvm/pr-subscribers-clang

Author: Nathan Ridge (HighCommander4)

Changes

Partially fixes #124450


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

2 Files Affected:

  • (modified) clang/lib/Sema/HeuristicResolver.cpp (+2-2)
  • (modified) clang/unittests/Sema/HeuristicResolverTest.cpp (+21)
diff --git a/clang/lib/Sema/HeuristicResolver.cpp b/clang/lib/Sema/HeuristicResolver.cpp
index e893afed71d268..6157191bafa6fc 100644
--- a/clang/lib/Sema/HeuristicResolver.cpp
+++ b/clang/lib/Sema/HeuristicResolver.cpp
@@ -133,8 +133,8 @@ TemplateName getReferencedTemplateName(const Type *T) {
 CXXRecordDecl *HeuristicResolverImpl::resolveTypeToRecordDecl(const Type *T) {
   assert(T);
 
-  // Unwrap type sugar such as type aliases.
-  T = T->getCanonicalTypeInternal().getTypePtr();
+  // Unwrap references and type sugar such as type aliases.
+  T = T->getCanonicalTypeInternal().getNonReferenceType().getTypePtr();
 
   if (const auto *DNT = T->getAs<DependentNameType>()) {
     T = resolveDeclsToType(resolveDependentNameType(DNT), Ctx)
diff --git a/clang/unittests/Sema/HeuristicResolverTest.cpp b/clang/unittests/Sema/HeuristicResolverTest.cpp
index 2b775b11719ea7..00e19aecdae0a9 100644
--- a/clang/unittests/Sema/HeuristicResolverTest.cpp
+++ b/clang/unittests/Sema/HeuristicResolverTest.cpp
@@ -213,6 +213,27 @@ TEST(HeuristicResolver, MemberExpr_Chained) {
       cxxMethodDecl(hasName("foo")).bind("output"));
 }
 
+TEST(HeuristicResolver, MemberExpr_ReferenceType) {
+  std::string Code = R"cpp(
+    struct B {
+      int waldo;
+    };
+    template <typename T>
+    struct A {
+      B &b;
+    };
+    template <typename T>
+    void foo(A<T> &a) {
+      a.b.waldo;
+    }
+  )cpp";
+  // Test resolution of "waldo" in "a.b.waldo".
+  expectResolution(
+      Code, &HeuristicResolver::resolveMemberExpr,
+      cxxDependentScopeMemberExpr(hasMemberName("waldo")).bind("input"),
+      fieldDecl(hasName("waldo")).bind("output"));
+}
+
 TEST(HeuristicResolver, MemberExpr_TemplateArgs) {
   std::string Code = R"cpp(
     struct Foo {

// Unwrap type sugar such as type aliases.
T = T->getCanonicalTypeInternal().getTypePtr();
// Unwrap references and type sugar such as type aliases.
T = T->getCanonicalTypeInternal().getNonReferenceType().getTypePtr();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it work if b were a pointer?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, the pointer case is a bit more involved because we bail here after failing to unwrap the pointee type here.

To handle it we will need to do something like:

  1. Check for pointer type and unwrap it if found
  2. Resolve BuiltinType::Dependent
  3. If a pointer type was not unwrapped at step (1), check for it again after step (2) and unwrap it if found

I was going to do this in a follow-up patch but it might make more sense to do it in the same patch; I will revise.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the revised version of the patch, we handle both reference and pointer types and we do it more robustly, checking for them after each step of simplification of the type.

…isticResolver::resolveMemberExpr()

Partially fixes #124450
@HighCommander4 HighCommander4 force-pushed the users/HighCommander4/issue-124450-1 branch from 9c8349f to 4ab3d58 Compare January 28, 2025 21:14
@HighCommander4 HighCommander4 changed the title [clang][Sema] Unwrap reference types in HeuristicResolverImpl::resolveTypeToRecordDecl() [clang][Sema] Handle pointer and reference type more robustly in HeuristicResolver::resolveMemberExpr() Jan 28, 2025
@HighCommander4 HighCommander4 marked this pull request as ready for review January 28, 2025 21:14
@HighCommander4
Copy link
Collaborator Author

(The Windows buildkite failure looks unrelated.)

@HighCommander4 HighCommander4 merged commit 7fd8426 into main Jan 30, 2025
8 of 10 checks passed
@HighCommander4 HighCommander4 deleted the users/HighCommander4/issue-124450-1 branch January 30, 2025 06:54
@kadircet
Copy link
Member

FWIW, i bisected a performance regression (and possibly an infinite loop) in clangd to this PR. trying to get a reproducer now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

HeuristicResolver cannot resolve chained dependent field access
4 participants