Skip to content

Commit 093af77

Browse files
[clangd] Avoid calling resolveTypeOfCallExpr() twice in HeuristicResolver::resolveExprToType() (#164353)
Fixes the performance regression reported at #156282 (comment)
1 parent 8298047 commit 093af77

File tree

2 files changed

+27
-0
lines changed

2 files changed

+27
-0
lines changed

clang/lib/Sema/HeuristicResolver.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,12 @@ QualType HeuristicResolverImpl::resolveExprToType(const Expr *E) {
450450
if (const auto *CE = dyn_cast<CallExpr>(E)) {
451451
if (QualType Resolved = resolveTypeOfCallExpr(CE); !Resolved.isNull())
452452
return Resolved;
453+
454+
// Don't proceed to try resolveExprToDecls(), it would just call
455+
// resolveTypeOfCallExpr() again.
456+
return E->getType();
453457
}
458+
454459
// Similarly, unwrapping a unary dereference operation does not work via
455460
// resolveExprToDecls.
456461
if (const auto *UO = dyn_cast<UnaryOperator>(E->IgnoreParenCasts())) {

clang/unittests/Sema/HeuristicResolverTest.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,28 @@ TEST(HeuristicResolver, MemberExpr_HangIssue126536) {
524524
cxxDependentScopeMemberExpr(hasMemberName("foo")).bind("input"));
525525
}
526526

527+
TEST(HeuristicResolver, MemberExpr_HangOnLongCallChain) {
528+
const size_t CallChainLength = 50;
529+
std::string Code = R"cpp(
530+
template <typename T>
531+
void foo(T t) {
532+
t
533+
)cpp";
534+
for (size_t I = 0; I < CallChainLength; ++I)
535+
Code.append(".method()\n");
536+
Code.append(R"cpp(
537+
.lastMethod();
538+
}
539+
)cpp");
540+
// Test that resolution of a name whose base is a long call chain
541+
// does not hang. Note that the hang for which this is a regression
542+
// test is finite (exponential runtime in the length of the chain),
543+
// so a "failure" here manifests as abnormally long runtime.
544+
expectResolution(
545+
Code, &HeuristicResolver::resolveMemberExpr,
546+
cxxDependentScopeMemberExpr(hasMemberName("lastMethod")).bind("input"));
547+
}
548+
527549
TEST(HeuristicResolver, MemberExpr_DefaultTemplateArgument) {
528550
std::string Code = R"cpp(
529551
struct Default {

0 commit comments

Comments
 (0)