Skip to content

Commit a4d17c4

Browse files
[clang][Sema] Generalize HeuristicResolver::resolveTypeToRecordDecl() to resolveTypeToTagDecl() (#124699)
1 parent 8578b81 commit a4d17c4

File tree

2 files changed

+37
-14
lines changed

2 files changed

+37
-14
lines changed

clang/lib/Sema/HeuristicResolver.cpp

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ class HeuristicResolverImpl {
7171

7272
// Helper function for HeuristicResolver::resolveDependentMember()
7373
// which takes a possibly-dependent type `T` and heuristically
74-
// resolves it to a CXXRecordDecl in which we can try name lookup.
75-
CXXRecordDecl *resolveTypeToRecordDecl(const Type *T);
74+
// resolves it to a TagDecl in which we can try name lookup.
75+
TagDecl *resolveTypeToTagDecl(const Type *T);
7676

7777
// This is a reimplementation of CXXRecordDecl::lookupDependentName()
7878
// so that the implementation can call into other HeuristicResolver helpers.
@@ -130,7 +130,7 @@ TemplateName getReferencedTemplateName(const Type *T) {
130130
// Helper function for HeuristicResolver::resolveDependentMember()
131131
// which takes a possibly-dependent type `T` and heuristically
132132
// resolves it to a CXXRecordDecl in which we can try name lookup.
133-
CXXRecordDecl *HeuristicResolverImpl::resolveTypeToRecordDecl(const Type *T) {
133+
TagDecl *HeuristicResolverImpl::resolveTypeToTagDecl(const Type *T) {
134134
assert(T);
135135

136136
// Unwrap type sugar such as type aliases.
@@ -144,8 +144,9 @@ CXXRecordDecl *HeuristicResolverImpl::resolveTypeToRecordDecl(const Type *T) {
144144
T = T->getCanonicalTypeInternal().getTypePtr();
145145
}
146146

147-
if (const auto *RT = T->getAs<RecordType>())
148-
return dyn_cast<CXXRecordDecl>(RT->getDecl());
147+
if (auto *TT = T->getAs<TagType>()) {
148+
return TT->getDecl();
149+
}
149150

150151
if (const auto *ICNT = T->getAs<InjectedClassNameType>())
151152
T = ICNT->getInjectedSpecializationType().getTypePtrOrNull();
@@ -278,7 +279,7 @@ HeuristicResolverImpl::resolveTypeOfCallExpr(const CallExpr *CE) {
278279
CalleeType = FnTypePtr->getPointeeType();
279280
if (const FunctionType *FnType = CalleeType->getAs<FunctionType>()) {
280281
if (const auto *D =
281-
resolveTypeToRecordDecl(FnType->getReturnType().getTypePtr())) {
282+
resolveTypeToTagDecl(FnType->getReturnType().getTypePtr())) {
282283
return {D};
283284
}
284285
}
@@ -389,11 +390,11 @@ bool findOrdinaryMember(const CXXRecordDecl *RD, CXXBasePath &Path,
389390
bool HeuristicResolverImpl::findOrdinaryMemberInDependentClasses(
390391
const CXXBaseSpecifier *Specifier, CXXBasePath &Path,
391392
DeclarationName Name) {
392-
CXXRecordDecl *RD =
393-
resolveTypeToRecordDecl(Specifier->getType().getTypePtr());
394-
if (!RD)
395-
return false;
396-
return findOrdinaryMember(RD, Path, Name);
393+
TagDecl *TD = resolveTypeToTagDecl(Specifier->getType().getTypePtr());
394+
if (const auto *RD = dyn_cast_if_present<CXXRecordDecl>(TD)) {
395+
return findOrdinaryMember(RD, Path, Name);
396+
}
397+
return false;
397398
}
398399

399400
std::vector<const NamedDecl *> HeuristicResolverImpl::lookupDependentName(
@@ -435,11 +436,14 @@ std::vector<const NamedDecl *> HeuristicResolverImpl::resolveDependentMember(
435436
const Type *T = QT.getTypePtrOrNull();
436437
if (!T)
437438
return {};
438-
if (auto *ET = T->getAs<EnumType>()) {
439-
auto Result = ET->getDecl()->lookup(Name);
439+
TagDecl *TD = resolveTypeToTagDecl(T);
440+
if (!TD)
441+
return {};
442+
if (auto *ED = dyn_cast<EnumDecl>(TD)) {
443+
auto Result = ED->lookup(Name);
440444
return {Result.begin(), Result.end()};
441445
}
442-
if (auto *RD = resolveTypeToRecordDecl(T)) {
446+
if (auto *RD = dyn_cast<CXXRecordDecl>(TD)) {
443447
if (!RD->hasDefinition())
444448
return {};
445449
RD = RD->getDefinition();

clang/unittests/Sema/HeuristicResolverTest.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,25 @@ TEST(HeuristicResolver, MemberExpr_Metafunction) {
295295
cxxMethodDecl(hasName("find")).bind("output"));
296296
}
297297

298+
TEST(HeuristicResolver, MemberExpr_Metafunction_Enumerator) {
299+
std::string Code = R"cpp(
300+
enum class State { Hidden };
301+
template <typename T>
302+
struct Meta {
303+
using Type = State;
304+
};
305+
template <typename T>
306+
void foo(typename Meta<T>::Type t) {
307+
t.Hidden;
308+
}
309+
)cpp";
310+
// Test resolution of "Hidden" in "t.Hidden".
311+
expectResolution(
312+
Code, &HeuristicResolver::resolveMemberExpr,
313+
cxxDependentScopeMemberExpr(hasMemberName("Hidden")).bind("input"),
314+
enumConstantDecl(hasName("Hidden")).bind("output"));
315+
}
316+
298317
TEST(HeuristicResolver, MemberExpr_DeducedNonTypeTemplateParameter) {
299318
std::string Code = R"cpp(
300319
template <int N>

0 commit comments

Comments
 (0)