https://github.com/firstmoonlight updated https://github.com/llvm/llvm-project/pull/190322
>From d45dc81e1e4a45c1d3c2d30888d5dca400013157 Mon Sep 17 00:00:00 2001 From: victorl <[email protected]> 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); + } +}; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
