Author: Matheus Izvekov
Date: 2026-07-09T21:51:37-03:00
New Revision: 9141f715500fecff8e3209b8f8da93715fecb5ca

URL: 
https://github.com/llvm/llvm-project/commit/9141f715500fecff8e3209b8f8da93715fecb5ca
DIFF: 
https://github.com/llvm/llvm-project/commit/9141f715500fecff8e3209b8f8da93715fecb5ca.diff

LOG: [clang] fix typo-correction for template name lookup (#208586)

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

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.md
    clang/lib/Sema/SemaTemplate.cpp
    clang/test/CXX/drs/cwg5xx.cpp
    clang/test/SemaCXX/typo-correction.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index d974e99680800..449a3792eb4ba 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -850,6 +850,7 @@ latest release, please see the [Clang Web 
Site](https://clang.llvm.org) or the
 - Clang no longer errors on overloads with 
diff erent 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