[clang] [clang][CodeComplete] Use HeuristicResolver to resolve DependentNameTypes (PR #123818)
Nathan Ridge via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 22 22:22:11 PST 2025
https://github.com/HighCommander4 updated https://github.com/llvm/llvm-project/pull/123818
>From 1b909be45a871d4942869ca93dfedac406fb72f1 Mon Sep 17 00:00:00 2001
From: Nathan Ridge <zeratul976 at hotmail.com>
Date: Tue, 21 Jan 2025 15:56:27 -0500
Subject: [PATCH] [clang][CodeComplete] Use HeuristicResolver to resolve
DependentNameTypes
Fixes https://github.com/clangd/clangd/issues/1249
---
clang/docs/ReleaseNotes.rst | 7 ++++++
clang/lib/Sema/SemaCodeComplete.cpp | 24 +++++++++++++++------
clang/test/CodeCompletion/member-access.cpp | 16 ++++++++++++++
3 files changed, 40 insertions(+), 7 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 75931bb25f06d9..a03f42ab910edd 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -1272,6 +1272,13 @@ libclang
- Added ``clang_getOffsetOfBase``, which allows computing the offset of a base
class in a class's layout.
+
+Code Completion
+---------------
+
+- Use ``HeuristicResolver`` (upstreamed from clangd) to improve code completion results
+ in dependent code
+
Static Analyzer
---------------
diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp
index 69cda6e68bd36b..58f3efbe0daf89 100644
--- a/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/clang/lib/Sema/SemaCodeComplete.cpp
@@ -5736,11 +5736,19 @@ class ConceptInfo {
// In particular, when E->getType() is DependentTy, try to guess a likely type.
// We accept some lossiness (like dropping parameters).
// We only try to handle common expressions on the LHS of MemberExpr.
-QualType getApproximateType(const Expr *E) {
+QualType getApproximateType(const Expr *E, HeuristicResolver &Resolver) {
if (E->getType().isNull())
return QualType();
E = E->IgnoreParenImpCasts();
QualType Unresolved = E->getType();
+ // Resolve DependentNameType
+ if (const auto *DNT = Unresolved->getAs<DependentNameType>()) {
+ if (auto Decls = Resolver.resolveDependentNameType(DNT);
+ Decls.size() == 1) {
+ if (const auto *TD = dyn_cast<TypeDecl>(Decls[0]))
+ return QualType(TD->getTypeForDecl(), 0);
+ }
+ }
// We only resolve DependentTy, or undeduced autos (including auto* etc).
if (!Unresolved->isSpecificBuiltinType(BuiltinType::Dependent)) {
AutoType *Auto = Unresolved->getContainedAutoType();
@@ -5749,7 +5757,7 @@ QualType getApproximateType(const Expr *E) {
}
// A call: approximate-resolve callee to a function type, get its return type
if (const CallExpr *CE = llvm::dyn_cast<CallExpr>(E)) {
- QualType Callee = getApproximateType(CE->getCallee());
+ QualType Callee = getApproximateType(CE->getCallee(), Resolver);
if (Callee.isNull() ||
Callee->isSpecificPlaceholderType(BuiltinType::BoundMember))
Callee = Expr::findBoundMemberType(CE->getCallee());
@@ -5792,7 +5800,7 @@ QualType getApproximateType(const Expr *E) {
if (const auto *CDSME = llvm::dyn_cast<CXXDependentScopeMemberExpr>(E)) {
QualType Base = CDSME->isImplicitAccess()
? CDSME->getBaseType()
- : getApproximateType(CDSME->getBase());
+ : getApproximateType(CDSME->getBase(), Resolver);
if (CDSME->isArrow() && !Base.isNull())
Base = Base->getPointeeType(); // could handle unique_ptr etc here?
auto *RD =
@@ -5813,14 +5821,15 @@ QualType getApproximateType(const Expr *E) {
if (const auto *DRE = llvm::dyn_cast<DeclRefExpr>(E)) {
if (const auto *VD = llvm::dyn_cast<VarDecl>(DRE->getDecl())) {
if (VD->hasInit())
- return getApproximateType(VD->getInit());
+ return getApproximateType(VD->getInit(), Resolver);
}
}
if (const auto *UO = llvm::dyn_cast<UnaryOperator>(E)) {
if (UO->getOpcode() == UnaryOperatorKind::UO_Deref) {
// We recurse into the subexpression because it could be of dependent
// type.
- if (auto Pointee = getApproximateType(UO->getSubExpr())->getPointeeType();
+ if (auto Pointee =
+ getApproximateType(UO->getSubExpr(), Resolver)->getPointeeType();
!Pointee.isNull())
return Pointee;
// Our caller expects a non-null result, even though the SubType is
@@ -5857,7 +5866,8 @@ void SemaCodeCompletion::CodeCompleteMemberReferenceExpr(
SemaRef.PerformMemberExprBaseConversion(Base, IsArrow);
if (ConvertedBase.isInvalid())
return;
- QualType ConvertedBaseType = getApproximateType(ConvertedBase.get());
+ QualType ConvertedBaseType =
+ getApproximateType(ConvertedBase.get(), Resolver);
enum CodeCompletionContext::Kind contextKind;
@@ -5896,7 +5906,7 @@ void SemaCodeCompletion::CodeCompleteMemberReferenceExpr(
return false;
Base = ConvertedBase.get();
- QualType BaseType = getApproximateType(Base);
+ QualType BaseType = getApproximateType(Base, Resolver);
if (BaseType.isNull())
return false;
ExprValueKind BaseKind = Base->getValueKind();
diff --git a/clang/test/CodeCompletion/member-access.cpp b/clang/test/CodeCompletion/member-access.cpp
index ab6dc69bf2923d..bf35f7ad021f71 100644
--- a/clang/test/CodeCompletion/member-access.cpp
+++ b/clang/test/CodeCompletion/member-access.cpp
@@ -401,3 +401,19 @@ struct node {
}
};
}
+
+namespace dependent_nested_class {
+template <typename T>
+struct Foo {
+ struct Bar {
+ int field;
+ };
+};
+template <typename T>
+void f() {
+ typename Foo<T>::Bar bar;
+ bar.field;
+ // RUN: %clang_cc1 -fsyntax-only -code-completion-at=%s:415:7 %s -o - | FileCheck -check-prefix=CHECK-DEPENDENT-NESTEDCLASS %s
+ // CHECK-DEPENDENT-NESTEDCLASS: [#int#]field
+}
+}
More information about the cfe-commits
mailing list