[clang] [clang][Sema] fix Crash when lookup finds UnresolvedUsingValueDecl followed by '<' (PR #190322)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Apr 3 01:21:23 PDT 2026
https://github.com/firstmoonlight updated https://github.com/llvm/llvm-project/pull/190322
>From d45dc81e1e4a45c1d3c2d30888d5dca400013157 Mon Sep 17 00:00:00 2001
From: victorl <ctos at DESKTOP-NDG29FO.localdomain>
Date: Fri, 3 Apr 2026 16:10:18 +0800
Subject: [PATCH] [clang][Sema] fix Crash in clang::Sema::ClassifyName when
calling overloaded using declarations
---
clang/lib/Sema/SemaDecl.cpp | 44 +++++++++++--------
.../SemaTemplate/lookup-dependent-using.cpp | 33 ++++++++++++++
2 files changed, 58 insertions(+), 19 deletions(-)
create mode 100644 clang/test/SemaTemplate/lookup-dependent-using.cpp
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 2951fd09294d8..498bfc25124cf 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -1156,26 +1156,32 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS,
IsFunctionTemplate = true;
Template = Context.getOverloadedTemplateName(Result.begin(),
Result.end());
- } else if (!Result.empty()) {
- auto *TD = cast<TemplateDecl>(getAsTemplateNameDecl(
- *Result.begin(), /*AllowFunctionTemplates=*/true,
- /*AllowDependent=*/false));
- IsFunctionTemplate = isa<FunctionTemplateDecl>(TD);
- IsVarTemplate = isa<VarTemplateDecl>(TD);
-
- UsingShadowDecl *FoundUsingShadow =
- dyn_cast<UsingShadowDecl>(*Result.begin());
- assert(!FoundUsingShadow ||
- TD == cast<TemplateDecl>(FoundUsingShadow->getTargetDecl()));
- Template = Context.getQualifiedTemplateName(
- SS.getScopeRep(),
- /*TemplateKeyword=*/false,
- FoundUsingShadow ? TemplateName(FoundUsingShadow) : TemplateName(TD));
} else {
- // All results were non-template functions. This is a function template
- // name.
- IsFunctionTemplate = true;
- Template = Context.getAssumedTemplateName(NameInfo.getName());
+ TemplateDecl *TD = nullptr;
+ if (!Result.empty()) {
+ TD = dyn_cast_or_null<TemplateDecl>(getAsTemplateNameDecl(
+ *Result.begin(), /*AllowFunctionTemplates=*/true,
+ /*AllowDependent=*/false));
+ }
+
+ if (TD) {
+ IsFunctionTemplate = isa<FunctionTemplateDecl>(TD);
+ IsVarTemplate = isa<VarTemplateDecl>(TD);
+
+ UsingShadowDecl *FoundUsingShadow =
+ dyn_cast<UsingShadowDecl>(*Result.begin());
+ assert(!FoundUsingShadow ||
+ TD == cast<TemplateDecl>(FoundUsingShadow->getTargetDecl()));
+ Template = Context.getQualifiedTemplateName(
+ SS.getScopeRep(),
+ /*TemplateKeyword=*/false,
+ FoundUsingShadow ? TemplateName(FoundUsingShadow) : TemplateName(TD));
+ } else {
+ // All results were non-template functions. This is a function template
+ // name.
+ IsFunctionTemplate = true;
+ Template = Context.getAssumedTemplateName(NameInfo.getName());
+ }
}
if (IsFunctionTemplate) {
diff --git a/clang/test/SemaTemplate/lookup-dependent-using.cpp b/clang/test/SemaTemplate/lookup-dependent-using.cpp
new file mode 100644
index 0000000000000..1dc0ba7ad29f3
--- /dev/null
+++ b/clang/test/SemaTemplate/lookup-dependent-using.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++20 %s
+// expected-no-diagnostics
+
+// This is a regression test that verifies handling a mix of using-declarations
+// from dependent and non-dependent base classes does not cause name lookup
+// to crash when a dependent entity cannot be converted to a TemplateDecl.
+
+template<typename A>
+class X {
+public:
+ template<typename T>
+ void execute(int a) {}
+};
+
+class Y {
+public:
+ void execute(int a) {}
+};
+
+template<typename A>
+class Exec : public X<A>, public Y {
+public:
+ using X<A>::execute;
+ using Y::execute;
+
+ void validate() {
+ // In C++20 the 'execute' here is followed by '<'.
+ // The lookup result will include an UnresolvedUsingValueDecl (from X<A>)
+ // and a UsingShadowDecl (from Y).
+ execute<int>(42);
+ execute(42);
+ }
+};
More information about the cfe-commits
mailing list