Skip to content

[clang][CodeComplete] Recurse into the subexpression of deref operator in getApproximateType #93404

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 2 commits into from
May 27, 2024

Conversation

zyn0217
Copy link
Contributor

@zyn0217 zyn0217 commented May 26, 2024

The issue with the previous implementation bc31be7 was that getApproximateType could potentially return a null QualType for a dereferencing operator, which is not what its caller wants.

…r in getApproximateType

The issue with the previous implementation bc31be7 was that
getApproximateType could potentially return a null QualType for a
dereferencing operator, which is not what its caller wants.
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels May 26, 2024
@llvmbot
Copy link
Member

llvmbot commented May 26, 2024

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-clang-tools-extra

Author: Younan Zhang (zyn0217)

Changes

The issue with the previous implementation bc31be7 was that getApproximateType could potentially return a null QualType for a dereferencing operator, which is not what its caller wants.


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

2 Files Affected:

  • (modified) clang/lib/Sema/SemaCodeComplete.cpp (+10-2)
  • (modified) clang/test/CodeCompletion/member-access.cpp (+16)
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index 328641ed94881..73ed99e099869 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -5680,8 +5680,16 @@ QualType getApproximateType(const Expr *E) {
     }
   }
   if (const auto *UO = llvm::dyn_cast<UnaryOperator>(E)) {
-    if (UO->getOpcode() == UnaryOperatorKind::UO_Deref)
-      return UO->getSubExpr()->getType()->getPointeeType();
+    if (UO->getOpcode() == UnaryOperatorKind::UO_Deref) {
+      // We recurse into the subexpression because it could be of dependent
+      // type.
+      QualType SubType = getApproximateType(UO->getSubExpr());
+      if (auto Pointee = SubType->getPointeeType(); !Pointee.isNull())
+        return Pointee;
+      // Our caller expects a non-null result, even though the SubType is
+      // supposed to have a pointee.
+      return SubType;
+    }
   }
   return Unresolved;
 }
diff --git a/clang/test/CodeCompletion/member-access.cpp b/clang/test/CodeCompletion/member-access.cpp
index 9f8c21c0bca6d..912f269db6c1a 100644
--- a/clang/test/CodeCompletion/member-access.cpp
+++ b/clang/test/CodeCompletion/member-access.cpp
@@ -367,4 +367,20 @@ class A {
 // CHECK-DEREF-THIS: [#void#]function()
   }
 };
+
+template <typename Element>
+struct RepeatedField {
+  void Add();
+};
+
+template <typename T>
+RepeatedField<T>* MutableRepeatedField() {}
+
+template <class T>
+void Foo() {
+  auto& C = *MutableRepeatedField<T>();
+  C.
+}
+// RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:382:5 %s -o - | FileCheck -check-prefix=CHECK-DEREF-DEPENDENT %s
+// CHECK-DEREF-DEPENDENT: [#void#]Add()
 }

Copy link
Collaborator

@HighCommander4 HighCommander4 left a comment

Choose a reason for hiding this comment

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

Thank you! Looks good with one suggested change.

return Pointee;
// Our caller expects a non-null result, even though the SubType is
// supposed to have a pointee.
return SubType;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Perhaps falling through to the return Unresolved would be better? That's a dependent representation of the pointee type, so it seems less misleading than returning the pointer type. (And it's also what other branches in this function do.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, I think that makes sense in the case of dereferencing a non-pointer type, which is ill-formed and we probably should offer nothing for completion.

@zyn0217
Copy link
Contributor Author

zyn0217 commented May 27, 2024

(I'll merge it shortly if CI turns green because I encountered the bug the other day in our codebase. Apologies I didn't point it out in my review for bc31be7)

@zyn0217 zyn0217 merged commit 7429950 into llvm:main May 27, 2024
8 checks passed
@zyn0217 zyn0217 deleted the no-crash-after-86466 branch May 27, 2024 07:56
qiaojbao pushed a commit to GPUOpen-Drivers/llvm-project that referenced this pull request Jun 26, 2024
…66abb8fcb

Local branch amd-gfx 49c66ab Merged main:b590ba73a76609bace9949ea8195d2ee8213cb3f into amd-gfx:300e9c581b42
Remote branch main 7429950 [clang][CodeComplete] Recurse into the subexpression of deref operator in getApproximateType (llvm#93404)
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 clang-tools-extra
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants