https://github.com/mizvekov updated https://github.com/llvm/llvm-project/pull/208586
>From c56b452a4e258f3d5899ca556f54316f60dc1e35 Mon Sep 17 00:00:00 2001 From: Matheus Izvekov <[email protected]> Date: Thu, 9 Jul 2026 20:18:38 -0300 Subject: [PATCH] [clang] fix typo-correction for template name lookup Only consider candidates which are templates. Disable spell checking for a DR test in order to not introduce noise, as spell checking is never helpful in those. Fixes #207498 --- clang/docs/ReleaseNotes.md | 1 + clang/lib/Sema/SemaTemplate.cpp | 20 +++++++++++++++++++- clang/test/CXX/drs/cwg5xx.cpp | 14 +++++++------- clang/test/SemaCXX/typo-correction.cpp | 22 ++++++++++++++++++++++ 4 files changed, 49 insertions(+), 8 deletions(-) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index 92e63585e492a..5c044b8272789 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -836,6 +836,7 @@ latest release, please see the [Clang Web Site](https://clang.llvm.org) or the - Clang no longer errors on overloads with different ref-qualifiers and constraints. (#GH120812) - Fixed a crash when a default argument is passed to an explicit object parameter. (#GH176639) - Fixed an alias template CTAD crash. +- Improvements to typo correction involving template names. (#GH207498) - Correctly diagnose uses of `co_await` / `co_yield` in the default argument of nested function declarations. (#GH98923) - Fixed a crash when diagnosing an invalid static member function with an explicit object parameter (#GH177741) - Clang incorrectly instantiated variable specializations outside of the immediate context. (#GH54439) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index ad0e653e254dd..43bcd0bfb9e17 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -515,7 +515,25 @@ bool Sema::LookupTemplateName(LookupResult &Found, Scope *S, CXXScopeSpec &SS, // to correct any typos. DeclarationName Name = Found.getLookupName(); Found.clear(); - QualifiedLookupValidatorCCC FilterCCC(!SS.isEmpty()); + + class TemplateNameLookupValidatorCCC final + : public QualifiedLookupValidatorCCC { + public: + using QualifiedLookupValidatorCCC::QualifiedLookupValidatorCCC; + + bool ValidateCandidate(const TypoCorrection &Candidate) final { + if (const NamedDecl *ND = Candidate.getCorrectionDecl(); + !ND || !isa<TemplateDecl>(ND)) + return false; + return QualifiedLookupValidatorCCC::ValidateCandidate(Candidate); + } + + std::unique_ptr<CorrectionCandidateCallback> clone() final { + return std::make_unique<TemplateNameLookupValidatorCCC>(*this); + } + }; + + TemplateNameLookupValidatorCCC FilterCCC(!SS.isEmpty()); FilterCCC.WantTypeSpecifiers = false; FilterCCC.WantExpressionKeywords = false; FilterCCC.WantRemainingKeywords = false; diff --git a/clang/test/CXX/drs/cwg5xx.cpp b/clang/test/CXX/drs/cwg5xx.cpp index 935f3c7e41dc3..4062fcc04ce3d 100644 --- a/clang/test/CXX/drs/cwg5xx.cpp +++ b/clang/test/CXX/drs/cwg5xx.cpp @@ -1,10 +1,10 @@ -// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-23,cxx98-11,cxx98-14,cxx98-17,cxx98 -// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-23,cxx98-11,cxx98-14,cxx98-17,since-cxx11 -// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-23,cxx98-14,cxx98-17,since-cxx11 -// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-23,since-cxx17,cxx98-17,since-cxx11 -// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-23,since-cxx20,since-cxx17,since-cxx11 -// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,cxx98-23,since-cxx23,since-cxx20,since-cxx17,since-cxx11 -// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -verify-directives -verify=expected,since-cxx26,since-cxx23,since-cxx20,since-cxx17,since-cxx11 +// RUN: %clang_cc1 -std=c++98 %s -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking -verify-directives -verify=expected,cxx98-23,cxx98-11,cxx98-14,cxx98-17,cxx98 +// RUN: %clang_cc1 -std=c++11 %s -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking -verify-directives -verify=expected,cxx98-23,cxx98-11,cxx98-14,cxx98-17,since-cxx11 +// RUN: %clang_cc1 -std=c++14 %s -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking -verify-directives -verify=expected,cxx98-23,cxx98-14,cxx98-17,since-cxx11 +// RUN: %clang_cc1 -std=c++17 %s -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking -verify-directives -verify=expected,cxx98-23,since-cxx17,cxx98-17,since-cxx11 +// RUN: %clang_cc1 -std=c++20 %s -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking -verify-directives -verify=expected,cxx98-23,since-cxx20,since-cxx17,since-cxx11 +// RUN: %clang_cc1 -std=c++23 %s -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking -verify-directives -verify=expected,cxx98-23,since-cxx23,since-cxx20,since-cxx17,since-cxx11 +// RUN: %clang_cc1 -std=c++2c %s -fexceptions -fcxx-exceptions -pedantic-errors -fno-spell-checking -verify-directives -verify=expected,since-cxx26,since-cxx23,since-cxx20,since-cxx17,since-cxx11 #if __cplusplus == 199711L #define static_assert(...) __extension__ _Static_assert(__VA_ARGS__) diff --git a/clang/test/SemaCXX/typo-correction.cpp b/clang/test/SemaCXX/typo-correction.cpp index d0478706021c7..9f124bec76cc2 100644 --- a/clang/test/SemaCXX/typo-correction.cpp +++ b/clang/test/SemaCXX/typo-correction.cpp @@ -805,3 +805,25 @@ namespace GH206992 { ::~F<void> {}; // expected-error@-1 {{destructor name 'F' does not refer to a template}} }; // namespace GH206992 + +namespace GH207498_1 { + void foo(); + namespace N { + namespace S {} + template <class> void foo() {} + // expected-note@-1 {{'N::foo' declared here}} + }; + template void N::S::foo<float>(); + // expected-error@-1 {{no template named 'foo' in namespace 'GH207498_1::N::S'; did you mean 'N::foo'?}} +} // namespace GH207498_1 + +namespace GH207498_2 { + template <class> void foo() {} + // expected-note@-1 {{'foo' declared here}} + namespace N { + namespace S {} + void foo(); + }; + template void N::S::foo<float>(); + // expected-error@-1 {{no template named 'foo' in namespace 'GH207498_2::N::S'; did you mean simply 'foo'?}} +} // namespace GH207498_2 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
