Skip to content

Commit

Permalink
[clang][Sema] Handle undeduced auto types in HeuristicResolver (#124236)
Browse files Browse the repository at this point in the history
  • Loading branch information
HighCommander4 authored Jan 24, 2025
1 parent ee05440 commit df9b31f
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 1 deletion.
17 changes: 16 additions & 1 deletion clang/lib/Sema/HeuristicResolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
}

Expand Down
40 changes: 40 additions & 0 deletions clang/unittests/Sema/HeuristicResolverTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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() {} };
Expand Down

0 comments on commit df9b31f

Please sign in to comment.