[clang] [clang][Sema] Fix assertion on invalid template template parameter during typo correction (PR #188239)

Haojian Wu via cfe-commits cfe-commits at lists.llvm.org
Tue Mar 24 05:26:02 PDT 2026


https://github.com/hokein created https://github.com/llvm/llvm-project/pull/188239

In the crash example, when performing typo correction for a qualified name lookup (`::a`),  clang suggests a template template parameter from an outer scope. 

However, template template parameters can not be qualified by  any scope. Attempting to combine the qualifier with the suggested template  template parameter resulted in an assertion failure in `ASTContext::getQualifiedTemplateName`:

This patch is to update the typo correction filter to reject `TemplateTemplateParmDecl` candidates when a qualifier is present . This prevents the invalid suggestion from being generated and avoids the assertion violation.

Fixes #183983 


>From 1a50b5c8d16666c673ae6924f9bf030fa278f072 Mon Sep 17 00:00:00 2001
From: Haojian Wu <hokein.wu at gmail.com>
Date: Tue, 24 Mar 2026 12:21:53 +0100
Subject: [PATCH] [clang][Sema] Fix assertion on invalid template template
 parameter during typo correction

---
 clang/lib/Sema/SemaTemplate.cpp      | 22 +++++++++++++++++++++-
 clang/test/SemaTemplate/gh183983.cpp | 10 ++++++++++
 2 files changed, 31 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/SemaTemplate/gh183983.cpp

diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 5d23660585ea5b..1e591a0f3c4e97 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -520,7 +520,27 @@ bool Sema::LookupTemplateName(LookupResult &Found, Scope *S, CXXScopeSpec &SS,
     DeclarationName Name = Found.getLookupName();
     Found.clear();
     // Simple filter callback that, for keywords, only accepts the C++ *_cast
-    DefaultFilterCCC FilterCCC{};
+    struct TemplateQualifierFilter final : CorrectionCandidateCallback {
+      const CXXScopeSpec &SS;
+      TemplateQualifierFilter(const CXXScopeSpec &SS) : SS(SS) {}
+      bool ValidateCandidate(const TypoCorrection &Candidate) override {
+        if (SS.isNotEmpty()) { // Qualified lookup
+          if (NamedDecl *ND = Candidate.getFoundDecl()) {
+            // A template template parameter is a name in the current template
+            // parameter list and cannot be validly qualified by any scope.
+            // Therefore, we should never suggest it as a typo correction for a
+            // qualified name.
+            if (isa<TemplateTemplateParmDecl>(ND))
+              return false;
+          }
+        }
+        return CorrectionCandidateCallback::ValidateCandidate(Candidate);
+      }
+      std::unique_ptr<CorrectionCandidateCallback> clone() override {
+        return std::make_unique<TemplateQualifierFilter>(*this);
+      }
+    };
+    TemplateQualifierFilter FilterCCC{SS};
     FilterCCC.WantTypeSpecifiers = false;
     FilterCCC.WantExpressionKeywords = false;
     FilterCCC.WantRemainingKeywords = false;
diff --git a/clang/test/SemaTemplate/gh183983.cpp b/clang/test/SemaTemplate/gh183983.cpp
new file mode 100644
index 00000000000000..368176290dba1e
--- /dev/null
+++ b/clang/test/SemaTemplate/gh183983.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// expected-error at 10 {{template template parameter requires 'class' or 'typename' after the parameter list}}
+// expected-error at 10 {{template template parameter must have its own template parameters}}
+// expected-error at 10 {{no template named 'a' in the global namespace}}
+// expected-note at 10 {{to match this '<'}}
+// expected-error at 10 {{expected expression}}
+// expected-error at 10 {{expected '>'}}
+// expected-error at 10 {{expected unqualified-id}}
+template <template <> a>::a <



More information about the cfe-commits mailing list