[clang] df9b31f - [clang][Sema] Handle undeduced auto types in HeuristicResolver (#124236)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Jan 24 13:11:22 PST 2025
Author: Nathan Ridge
Date: 2025-01-24T16:11:18-05:00
New Revision: df9b31f1e0cdb8096e9d2e0749e473dd815b39f7
URL: https://github.com/llvm/llvm-project/commit/df9b31f1e0cdb8096e9d2e0749e473dd815b39f7
DIFF: https://github.com/llvm/llvm-project/commit/df9b31f1e0cdb8096e9d2e0749e473dd815b39f7.diff
LOG: [clang][Sema] Handle undeduced auto types in HeuristicResolver (#124236)
Fixes https://github.com/clangd/clangd/issues/897
Added:
Modified:
clang/lib/Sema/HeuristicResolver.cpp
clang/unittests/Sema/HeuristicResolverTest.cpp
Removed:
################################################################################
diff --git a/clang/lib/Sema/HeuristicResolver.cpp b/clang/lib/Sema/HeuristicResolver.cpp
index 2a726fe51d355e..e893afed71d268 100644
--- a/clang/lib/Sema/HeuristicResolver.cpp
+++ b/clang/lib/Sema/HeuristicResolver.cpp
@@ -227,6 +227,7 @@ std::vector<const NamedDecl *> HeuristicResolverImpl::resolveMemberExpr(
}
// Try resolving the member inside the expression's base type.
+ Expr *Base = ME->isImplicitAccess() ? nullptr : ME->getBase();
QualType BaseType = ME->getBaseType();
if (ME->isArrow()) {
BaseType = getPointeeType(BaseType);
@@ -237,11 +238,25 @@ std::vector<const NamedDecl *> HeuristicResolverImpl::resolveMemberExpr(
// If BaseType is the type of a dependent expression, it's just
// represented as BuiltinType::Dependent which gives us no information. We
// can get further by analyzing the dependent expression.
- Expr *Base = ME->isImplicitAccess() ? nullptr : ME->getBase();
if (Base && BT->getKind() == BuiltinType::Dependent) {
BaseType = resolveExprToType(Base);
}
}
+ if (const auto *AT = BaseType->getContainedAutoType()) {
+ // If BaseType contains a dependent `auto` type, deduction will not have
+ // been performed on it yet. In simple cases (e.g. `auto` variable with
+ // initializer), get the approximate type that would result from deduction.
+ // FIXME: A more accurate implementation would propagate things like the
+ // `const` in `const auto`.
+ if (AT->isUndeducedAutoType()) {
+ if (const auto *DRE = dyn_cast<DeclRefExpr>(Base)) {
+ if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
+ if (VD->hasInit())
+ BaseType = resolveExprToType(VD->getInit());
+ }
+ }
+ }
+ }
return resolveDependentMember(BaseType, ME->getMember(), NoFilter);
}
diff --git a/clang/unittests/Sema/HeuristicResolverTest.cpp b/clang/unittests/Sema/HeuristicResolverTest.cpp
index 2cd5486b3227f0..2b775b11719ea7 100644
--- a/clang/unittests/Sema/HeuristicResolverTest.cpp
+++ b/clang/unittests/Sema/HeuristicResolverTest.cpp
@@ -155,6 +155,46 @@ TEST(HeuristicResolver, MemberExpr_SmartPointer_Qualified) {
cxxMethodDecl(hasName("find"), isConst()).bind("output"));
}
+TEST(HeuristicResolver, MemberExpr_AutoTypeDeduction1) {
+ std::string Code = R"cpp(
+ template <typename T>
+ struct A {
+ int waldo;
+ };
+ template <typename T>
+ void foo(A<T> a) {
+ auto copy = a;
+ copy.waldo;
+ }
+ )cpp";
+ expectResolution(
+ Code, &HeuristicResolver::resolveMemberExpr,
+ cxxDependentScopeMemberExpr(hasMemberName("waldo")).bind("input"),
+ fieldDecl(hasName("waldo")).bind("output"));
+}
+
+TEST(HeuristicResolver, MemberExpr_AutoTypeDeduction2) {
+ std::string Code = R"cpp(
+ struct B {
+ int waldo;
+ };
+
+ template <typename T>
+ struct A {
+ B b;
+ };
+ template <typename T>
+ void foo(A<T> a) {
+ auto b = a.b;
+ b.waldo;
+ }
+ )cpp";
+ expectResolution(
+ Code, &HeuristicResolver::resolveMemberExpr,
+ cxxDependentScopeMemberExpr(hasMemberName("waldo")).bind("input"),
+ fieldDecl(hasName("waldo")).bind("output"));
+}
+
TEST(HeuristicResolver, MemberExpr_Chained) {
std::string Code = R"cpp(
struct A { void foo() {} };
More information about the cfe-commits
mailing list