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

Reply via email to