[clang] [Clang] Fix another concept cache bug (PR #162272)

Younan Zhang via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 7 05:21:27 PDT 2025


https://github.com/zyn0217 created https://github.com/llvm/llvm-project/pull/162272

We previously failed to profile dependent CallExprs; this patch corrects that behavior. We now also profile canonical types whenever possible, since type sugar has little impact on hash computation.

>From b44ac2ace2beb4650d3acf93bdf7599f23a98b75 Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Tue, 7 Oct 2025 20:16:05 +0800
Subject: [PATCH] [Clang] Fix another concept cache bug

We previously failed to profile dependent CallExprs; this patch corrects
that behavior. We now also profile canonical types whenever possible,
since type sugar has little impact on hash computation.
---
 clang/lib/Sema/SemaConcept.cpp | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp
index 8946f1bfc7a95..f4df63c1d2243 100644
--- a/clang/lib/Sema/SemaConcept.cpp
+++ b/clang/lib/Sema/SemaConcept.cpp
@@ -305,6 +305,12 @@ class HashParameterMapping : public RecursiveASTVisitor<HashParameterMapping> {
     if (!NTTP)
       return TraverseDecl(D);
 
+    if (NTTP->getDepth() >= TemplateArgs.getNumLevels())
+      return true;
+
+    if (!TemplateArgs.hasTemplateArgument(NTTP->getDepth(), NTTP->getIndex()))
+      return true;
+
     TemplateArgument Arg = TemplateArgs(NTTP->getDepth(), NTTP->getPosition());
     if (NTTP->isParameterPack() && SemaRef.ArgPackSubstIndex) {
       assert(Arg.getKind() == TemplateArgument::Pack &&
@@ -331,17 +337,25 @@ class HashParameterMapping : public RecursiveASTVisitor<HashParameterMapping> {
     return inherited::TraverseDecl(D);
   }
 
+  bool TraverseCallExpr(CallExpr *CE) {
+    inherited::TraverseStmt(CE->getCallee());
+
+    for (Expr *Arg : CE->arguments())
+      inherited::TraverseStmt(Arg);
+
+    return true;
+  }
+
   bool TraverseTypeLoc(TypeLoc TL, bool TraverseQualifier = true) {
     // We don't care about TypeLocs. So traverse Types instead.
-    return TraverseType(TL.getType(), TraverseQualifier);
+    return TraverseType(TL.getType().getCanonicalType(), TraverseQualifier);
   }
 
   bool TraverseTagType(const TagType *T, bool TraverseQualifier) {
     // T's parent can be dependent while T doesn't have any template arguments.
     // We should have already traversed its qualifier.
     // FIXME: Add an assert to catch cases where we failed to profile the
-    // concept. assert(!T->isDependentType() && "We missed a case in profiling
-    // concepts!");
+    // concept.
     return true;
   }
 
@@ -706,7 +720,6 @@ ExprResult ConstraintSatisfactionChecker::Evaluate(
 
   if (auto Iter = S.UnsubstitutedConstraintSatisfactionCache.find(ID);
       Iter != S.UnsubstitutedConstraintSatisfactionCache.end()) {
-
     auto &Cached = Iter->second.Satisfaction;
     Satisfaction.ContainsErrors = Cached.ContainsErrors;
     Satisfaction.IsSatisfied = Cached.IsSatisfied;



More information about the cfe-commits mailing list