-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[clangd] Use HeuristicResolver to try to resolve dependent 'auto' #156283
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
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
… getApproximateType() in HeuristicResolver After this change, HeuristicResolver should be able to do everything that SemaCodeComplete's getApproximateType() can do (and more).
… with calls to HeuristicResolver
Collaborator
Author
|
Depends on #156282 |
Member
|
@llvm/pr-subscribers-clang-tools-extra @llvm/pr-subscribers-clangd Author: Nathan Ridge (HighCommander4) ChangesFixes clangd/clangd#2431 Full diff: https://github.com/llvm/llvm-project/pull/156283.diff 9 Files Affected:
diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp
index 2f46ecc92576c..b96a84519e78c 100644
--- a/clang-tools-extra/clangd/AST.cpp
+++ b/clang-tools-extra/clangd/AST.cpp
@@ -29,6 +29,7 @@
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Index/USRGeneration.h"
+#include "clang/Sema/HeuristicResolver.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallSet.h"
@@ -479,10 +480,12 @@ namespace {
/// a deduced type set. The AST should be improved to simplify this scenario.
class DeducedTypeVisitor : public RecursiveASTVisitor<DeducedTypeVisitor> {
SourceLocation SearchedLocation;
+ const HeuristicResolver *Resolver;
public:
- DeducedTypeVisitor(SourceLocation SearchedLocation)
- : SearchedLocation(SearchedLocation) {}
+ DeducedTypeVisitor(SourceLocation SearchedLocation,
+ const HeuristicResolver *Resolver)
+ : SearchedLocation(SearchedLocation), Resolver(Resolver) {}
// Handle auto initializers:
//- auto i = 1;
@@ -499,6 +502,14 @@ class DeducedTypeVisitor : public RecursiveASTVisitor<DeducedTypeVisitor> {
return true;
if (auto *AT = D->getType()->getContainedAutoType()) {
+ if (AT->isUndeducedAutoType()) {
+ if (const auto *VD = dyn_cast<VarDecl>(D)) {
+ if (Resolver && VD->hasInit()) {
+ DeducedType = Resolver->resolveExprToType(VD->getInit());
+ return true;
+ }
+ }
+ }
DeducedType = AT->desugar();
}
return true;
@@ -608,10 +619,12 @@ class DeducedTypeVisitor : public RecursiveASTVisitor<DeducedTypeVisitor> {
};
} // namespace
-std::optional<QualType> getDeducedType(ASTContext &ASTCtx, SourceLocation Loc) {
+std::optional<QualType> getDeducedType(ASTContext &ASTCtx,
+ const HeuristicResolver *Resolver,
+ SourceLocation Loc) {
if (!Loc.isValid())
return {};
- DeducedTypeVisitor V(Loc);
+ DeducedTypeVisitor V(Loc, Resolver);
V.TraverseAST(ASTCtx);
if (V.DeducedType.isNull())
return std::nullopt;
diff --git a/clang-tools-extra/clangd/AST.h b/clang-tools-extra/clangd/AST.h
index 1538d12172593..2b83595e5b8e9 100644
--- a/clang-tools-extra/clangd/AST.h
+++ b/clang-tools-extra/clangd/AST.h
@@ -31,6 +31,7 @@ namespace clang {
class SourceManager;
class Decl;
class DynTypedNode;
+class HeuristicResolver;
namespace clangd {
@@ -167,7 +168,8 @@ QualType declaredType(const TypeDecl *D);
/// Retrieves the deduced type at a given location (auto, decltype).
/// It will return the underlying type.
/// If the type is an undeduced auto, returns the type itself.
-std::optional<QualType> getDeducedType(ASTContext &, SourceLocation Loc);
+std::optional<QualType> getDeducedType(ASTContext &, const HeuristicResolver *,
+ SourceLocation Loc);
// Find the abbreviated-function-template `auto` within a type, or returns null.
// Similar to getContainedAutoTypeLoc, but these `auto`s are
diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp
index 9eec322fe5963..138544dea99a1 100644
--- a/clang-tools-extra/clangd/Hover.cpp
+++ b/clang-tools-extra/clangd/Hover.cpp
@@ -1309,7 +1309,9 @@ std::optional<HoverInfo> getHover(ParsedAST &AST, Position Pos,
}
} else if (Tok.kind() == tok::kw_auto || Tok.kind() == tok::kw_decltype) {
HoverCountMetric.record(1, "keyword");
- if (auto Deduced = getDeducedType(AST.getASTContext(), Tok.location())) {
+ if (auto Deduced =
+ getDeducedType(AST.getASTContext(), AST.getHeuristicResolver(),
+ Tok.location())) {
HI = getDeducedTypeHoverContents(*Deduced, Tok, AST.getASTContext(), PP,
Index);
HighlightRange = Tok.range(SM).toCharRange(SM);
diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp
index a253a630a48cc..18bc29426df29 100644
--- a/clang-tools-extra/clangd/XRefs.cpp
+++ b/clang-tools-extra/clangd/XRefs.cpp
@@ -806,7 +806,9 @@ std::vector<LocatedSymbol> locateSymbolAt(ParsedAST &AST, Position Pos,
if (Tok.kind() == tok::kw_auto || Tok.kind() == tok::kw_decltype) {
// go-to-definition on auto should find the definition of the deduced
// type, if possible
- if (auto Deduced = getDeducedType(AST.getASTContext(), Tok.location())) {
+ if (auto Deduced =
+ getDeducedType(AST.getASTContext(), AST.getHeuristicResolver(),
+ Tok.location())) {
auto LocSym = locateSymbolForType(AST, *Deduced, Index);
if (!LocSym.empty())
return LocSym;
@@ -1965,7 +1967,7 @@ std::vector<const CXXRecordDecl *> findRecordTypeAt(ParsedAST &AST,
// Return the type most associated with an AST node.
// This isn't precisely defined: we want "go to type" to do something useful.
-static QualType typeForNode(const ASTContext &Ctx,
+static QualType typeForNode(const ASTContext &Ctx, const HeuristicResolver *H,
const SelectionTree::Node *N) {
// If we're looking at a namespace qualifier, walk up to what it's qualifying.
// (If we're pointing at a *class* inside a NNS, N will be a TypeLoc).
@@ -1978,7 +1980,7 @@ static QualType typeForNode(const ASTContext &Ctx,
if (const TypeLoc *TL = N->ASTNode.get<TypeLoc>()) {
if (llvm::isa<DeducedType>(TL->getTypePtr()))
if (auto Deduced = getDeducedType(
- N->getDeclContext().getParentASTContext(), TL->getBeginLoc()))
+ N->getDeclContext().getParentASTContext(), H, TL->getBeginLoc()))
return *Deduced;
// Exception: an alias => underlying type.
if (llvm::isa<TypedefType>(TL->getTypePtr()))
@@ -2161,7 +2163,8 @@ std::vector<LocatedSymbol> findType(ParsedAST &AST, Position Pos,
// information about the type you may have not known before
// (since unique_ptr<unique_ptr<T>> != unique_ptr<T>).
for (const QualType &Type : unwrapFindType(
- typeForNode(AST.getASTContext(), N), AST.getHeuristicResolver()))
+ typeForNode(AST.getASTContext(), AST.getHeuristicResolver(), N),
+ AST.getHeuristicResolver()))
llvm::copy(locateSymbolForType(AST, Type, Index),
std::back_inserter(LocatedSymbols));
diff --git a/clang-tools-extra/clangd/refactor/tweaks/ExpandDeducedType.cpp b/clang-tools-extra/clangd/refactor/tweaks/ExpandDeducedType.cpp
index fec5f5797cb62..52afda56a5028 100644
--- a/clang-tools-extra/clangd/refactor/tweaks/ExpandDeducedType.cpp
+++ b/clang-tools-extra/clangd/refactor/tweaks/ExpandDeducedType.cpp
@@ -133,7 +133,8 @@ Expected<Tweak::Effect> ExpandDeducedType::apply(const Selection &Inputs) {
auto &SrcMgr = Inputs.AST->getSourceManager();
std::optional<clang::QualType> DeducedType =
- getDeducedType(Inputs.AST->getASTContext(), Range.getBegin());
+ getDeducedType(Inputs.AST->getASTContext(),
+ Inputs.AST->getHeuristicResolver(), Range.getBegin());
// if we can't resolve the type, return an error message
if (DeducedType == std::nullopt || (*DeducedType)->isUndeducedAutoType())
diff --git a/clang-tools-extra/clangd/unittests/ASTTests.cpp b/clang-tools-extra/clangd/unittests/ASTTests.cpp
index 76d46bad82224..91ae727d8c944 100644
--- a/clang-tools-extra/clangd/unittests/ASTTests.cpp
+++ b/clang-tools-extra/clangd/unittests/ASTTests.cpp
@@ -244,7 +244,8 @@ TEST(GetDeducedType, KwAutoKwDecltypeExpansion) {
for (Position Pos : File.points()) {
auto Location = sourceLocationInMainFile(SM.get(), Pos);
ASSERT_TRUE(!!Location) << llvm::toString(Location.takeError());
- auto DeducedType = getDeducedType(AST.getASTContext(), *Location);
+ auto DeducedType = getDeducedType(AST.getASTContext(),
+ AST.getHeuristicResolver(), *Location);
if (T.DeducedType == nullptr) {
EXPECT_FALSE(DeducedType);
} else {
diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp
index 743c0dc0d0187..e9abf71e6d1b6 100644
--- a/clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -481,7 +481,7 @@ class Foo final {})cpp";
[](HoverInfo &HI) {
HI.Name = "auto";
HI.Kind = index::SymbolKind::TypeAlias;
- HI.Definition = "/* not deduced */";
+ HI.Definition = "T";
}},
// constrained auto
{R"cpp(
@@ -2657,7 +2657,7 @@ TEST(Hover, All) {
[](HoverInfo &HI) {
HI.Name = "auto";
HI.Kind = index::SymbolKind::TypeAlias;
- HI.Definition = "/* not deduced */";
+ HI.Definition = "T";
}},
{
R"cpp(// Undeduced auto return type
diff --git a/clang-tools-extra/clangd/unittests/XRefsTests.cpp b/clang-tools-extra/clangd/unittests/XRefsTests.cpp
index 17204a47ba3bc..7ed08d7cce3d3 100644
--- a/clang-tools-extra/clangd/unittests/XRefsTests.cpp
+++ b/clang-tools-extra/clangd/unittests/XRefsTests.cpp
@@ -924,11 +924,19 @@ TEST(LocateSymbol, All) {
}
)cpp",
+ R"cpp(// auto with dependent type
+ template <typename>
+ struct [[A]] {};
+ template <typename T>
+ void foo(A<T> a) {
+ ^auto copy = a;
+ }
+ )cpp",
+
R"cpp(// Override specifier jumps to overridden method
class Y { virtual void $decl[[a]]() = 0; };
class X : Y { void a() ^override {} };
)cpp",
-
R"cpp(// Final specifier jumps to overridden method
class Y { virtual void $decl[[a]]() = 0; };
class X : Y { void a() ^final {} };
diff --git a/clang-tools-extra/clangd/unittests/tweaks/ExpandDeducedTypeTests.cpp b/clang-tools-extra/clangd/unittests/tweaks/ExpandDeducedTypeTests.cpp
index 8da394d74b54d..3a53c11839c20 100644
--- a/clang-tools-extra/clangd/unittests/tweaks/ExpandDeducedTypeTests.cpp
+++ b/clang-tools-extra/clangd/unittests/tweaks/ExpandDeducedTypeTests.cpp
@@ -47,7 +47,7 @@ TEST_F(ExpandDeducedTypeTest, Test) {
"namespace ns { void f() { Class C = Class(); } }");
// undefined functions should not be replaced
EXPECT_THAT(apply("au^to x = doesnt_exist(); // error-ok"),
- StartsWith("fail: Could not deduce type for 'auto' type"));
+ StartsWith("fail: Could not expand a dependent type"));
// function pointers should not be replaced
EXPECT_THAT(apply("au^to x = &ns::Func;"),
StartsWith("fail: Could not expand type"));
@@ -91,7 +91,7 @@ TEST_F(ExpandDeducedTypeTest, Test) {
// unknown types in a template should not be replaced
EXPECT_THAT(apply("template <typename T> void x() { ^auto y = T::z(); }"),
- StartsWith("fail: Could not deduce type for 'auto' type"));
+ StartsWith("fail: Could not expand a dependent type"));
// check primitive type
EXPECT_EQ(apply("decl^type(0) i;"), "int i;");
|
This was referenced Sep 1, 2025
zyn0217
approved these changes
Sep 2, 2025
Contributor
zyn0217
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Base automatically changed from
users/HighCommander4/issue-2432-review
to
main
September 16, 2025 19:18
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes clangd/clangd#2431