Author: Haojian Wu
Date: 2026-03-27T14:58:44+01:00
New Revision: 79ffad69f45821afddb0a5acc9a55dbf5f3d3e90

URL: 
https://github.com/llvm/llvm-project/commit/79ffad69f45821afddb0a5acc9a55dbf5f3d3e90
DIFF: 
https://github.com/llvm/llvm-project/commit/79ffad69f45821afddb0a5acc9a55dbf5f3d3e90.diff

LOG: [clang][Sema] Fix assertion on invalid template template parameter during 
typo correction (#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

Added: 
    clang/test/SemaTemplate/gh183983.cpp

Modified: 
    clang/include/clang/Sema/TypoCorrection.h
    clang/lib/Sema/SemaCXXScopeSpec.cpp
    clang/lib/Sema/SemaTemplate.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Sema/TypoCorrection.h 
b/clang/include/clang/Sema/TypoCorrection.h
index 1d780c45efd55..0c882d3f796fe 100644
--- a/clang/include/clang/Sema/TypoCorrection.h
+++ b/clang/include/clang/Sema/TypoCorrection.h
@@ -350,6 +350,34 @@ class CorrectionCandidateCallback {
   NestedNameSpecifier TypoNNS;
 };
 
+/// Callback class to reject typo corrections that look like template 
parameters
+/// when doing a qualified lookup. A template parameter (type or template) is
+/// local to the current template scope and cannot be validly qualified by any
+/// external scope (e.g. 'std::T' where T is a template parameter).
+class QualifiedLookupValidatorCCC : public CorrectionCandidateCallback {
+public:
+  explicit QualifiedLookupValidatorCCC(bool HasQualifier)
+      : HasQualifier(HasQualifier) {}
+
+  bool ValidateCandidate(const TypoCorrection &Candidate) override {
+    if (HasQualifier) {
+      if (const NamedDecl *ND = Candidate.getCorrectionDecl()) {
+        // A template parameter can never be a member of any qualifier scope.
+        if (isa<TemplateTypeParmDecl>(ND) || isa<TemplateTemplateParmDecl>(ND))
+          return false;
+      }
+    }
+    return CorrectionCandidateCallback::ValidateCandidate(Candidate);
+  }
+
+  std::unique_ptr<CorrectionCandidateCallback> clone() override {
+    return std::make_unique<QualifiedLookupValidatorCCC>(*this);
+  }
+
+private:
+  bool HasQualifier;
+};
+
 class DefaultFilterCCC final : public CorrectionCandidateCallback {
 public:
   explicit DefaultFilterCCC(const IdentifierInfo *Typo = nullptr,

diff  --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp 
b/clang/lib/Sema/SemaCXXScopeSpec.cpp
index a4a25a4f44602..9641395b68ae5 100644
--- a/clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -19,6 +19,7 @@
 #include "clang/Sema/DeclSpec.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Template.h"
+#include "clang/Sema/TypoCorrection.h"
 #include "llvm/ADT/STLExtras.h"
 using namespace clang;
 
@@ -379,18 +380,17 @@ namespace {
 // Callback to only accept typo corrections that can be a valid C++ member
 // initializer: either a non-static field member or a base class.
 class NestedNameSpecifierValidatorCCC final
-    : public CorrectionCandidateCallback {
+    : public QualifiedLookupValidatorCCC {
 public:
   explicit NestedNameSpecifierValidatorCCC(Sema &SRef, bool HasQualifier)
-      : SRef(SRef), HasQualifier(HasQualifier) {}
+      : QualifiedLookupValidatorCCC(HasQualifier), SRef(SRef) {}
 
   bool ValidateCandidate(const TypoCorrection &candidate) override {
+    if (!QualifiedLookupValidatorCCC::ValidateCandidate(candidate))
+      return false;
     const NamedDecl *ND = candidate.getCorrectionDecl();
     if (!SRef.isAcceptableNestedNameSpecifier(ND))
       return false;
-    // A template type parameter cannot have a nested name specifier.
-    if (HasQualifier && isa<TemplateTypeParmDecl>(ND))
-      return false;
     return true;
   }
 
@@ -399,10 +399,8 @@ class NestedNameSpecifierValidatorCCC final
   }
 
  private:
-  Sema &SRef;
-  bool HasQualifier;
+   Sema &SRef;
 };
-
 }
 
 [[nodiscard]] static bool ExtendNestedNameSpecifier(Sema &S, CXXScopeSpec &SS,

diff  --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 5d23660585ea5..aa72cb8fa2895 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -519,8 +519,7 @@ bool Sema::LookupTemplateName(LookupResult &Found, Scope 
*S, CXXScopeSpec &SS,
     // to correct any typos.
     DeclarationName Name = Found.getLookupName();
     Found.clear();
-    // Simple filter callback that, for keywords, only accepts the C++ *_cast
-    DefaultFilterCCC FilterCCC{};
+    QualifiedLookupValidatorCCC FilterCCC(!SS.isEmpty());
     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 0000000000000..368176290dba1
--- /dev/null
+++ b/clang/test/SemaTemplate/gh183983.cpp
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+// expected-error@10 {{template template parameter requires 'class' or 
'typename' after the parameter list}}
+// expected-error@10 {{template template parameter must have its own template 
parameters}}
+// expected-error@10 {{no template named 'a' in the global namespace}}
+// expected-note@10 {{to match this '<'}}
+// expected-error@10 {{expected expression}}
+// expected-error@10 {{expected '>'}}
+// expected-error@10 {{expected unqualified-id}}
+template <template <> a>::a <


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to