https://github.com/zyn0217 updated https://github.com/llvm/llvm-project/pull/210498
>From 21c7841860e3e8a3dcb1f3eaf97b7dac945bb6e5 Mon Sep 17 00:00:00 2001 From: Younan Zhang <[email protected]> Date: Sat, 18 Jul 2026 17:38:57 +0800 Subject: [PATCH 1/2] [Clang] Add NormalizedConstraint::dump() This facilitates debugging with NormalizedConstraints, particularly when checking parameter mappings. --- clang/include/clang/AST/TemplateBase.h | 2 + clang/include/clang/Sema/SemaConcept.h | 3 + clang/lib/AST/TemplateBase.cpp | 26 +++++ clang/lib/Sema/SemaConcept.cpp | 150 +++++++++++++++++++++++++ 4 files changed, 181 insertions(+) diff --git a/clang/include/clang/AST/TemplateBase.h b/clang/include/clang/AST/TemplateBase.h index c0db55ea92cd5..f7d754ea6082b 100644 --- a/clang/include/clang/AST/TemplateBase.h +++ b/clang/include/clang/AST/TemplateBase.h @@ -295,6 +295,8 @@ class TemplateArgument { /// Return the kind of stored template argument. ArgKind getKind() const { return (ArgKind)TypeOrValue.Kind; } + StringRef getKindName() const; + /// Determine whether this template argument has no value. bool isNull() const { return getKind() == Null; } diff --git a/clang/include/clang/Sema/SemaConcept.h b/clang/include/clang/Sema/SemaConcept.h index bdd997b18cb08..4bf251d351f06 100644 --- a/clang/include/clang/Sema/SemaConcept.h +++ b/clang/include/clang/Sema/SemaConcept.h @@ -276,6 +276,9 @@ struct NormalizedConstraint { SourceRange getSourceRange() const { return {getBeginLoc(), getEndLoc()}; } + void dump(ASTContext &Context) const; + void dump(llvm::raw_ostream &OS, ASTContext &Context) const; + private: friend class Sema; static NormalizedConstraint * diff --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp index a5e0dde45364c..d64d3bd5dcc30 100644 --- a/clang/lib/AST/TemplateBase.cpp +++ b/clang/lib/AST/TemplateBase.cpp @@ -258,6 +258,32 @@ TemplateArgument::CreatePackCopy(ASTContext &Context, return TemplateArgument(Args.copy(Context)); } +StringRef TemplateArgument::getKindName() const { + switch (getKind()) { + case TemplateArgument::Null: + return "null"; + case TemplateArgument::Type: + return "type"; + case TemplateArgument::Declaration: + return "decl"; + case TemplateArgument::NullPtr: + return "nullptr"; + case TemplateArgument::Integral: + return "integral"; + case TemplateArgument::Template: + return "template"; + case TemplateArgument::TemplateExpansion: + return "template expansion"; + case TemplateArgument::Expression: + return "expression"; + case TemplateArgument::Pack: + return "pack"; + case TemplateArgument::StructuralValue: + return "structural value"; + } + llvm_unreachable("unhandled ArgKind"); +} + TemplateArgumentDependence TemplateArgument::getDependence() const { auto Deps = TemplateArgumentDependence::None; switch (getKind()) { diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 8831a26224e7d..98d3951c491b0 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -17,6 +17,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/ExprConcepts.h" #include "clang/AST/RecursiveASTVisitor.h" +#include "clang/AST/TextNodeDumper.h" #include "clang/Basic/OperatorPrecedence.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Initialization.h" @@ -30,6 +31,7 @@ #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Support/SaveAndRestore.h" +#include "llvm/Support/ScopedPrinter.h" #include "llvm/Support/TimeProfiler.h" using namespace clang; @@ -2965,3 +2967,151 @@ bool SubsumptionChecker::Subsumes(Literal A, Literal B) { } llvm_unreachable("unknown literal kind"); } + +namespace { + +class DumpNormalizedConstraint { + raw_ostream &OS; + const PrintingPolicy &PP; + TextNodeDumper TD; + +public: + DumpNormalizedConstraint(raw_ostream &OS, ASTContext &Context) + : OS(OS), PP(Context.getPrintingPolicy()), + TD(OS, Context, /*ShowColors=*/false) {} + + void dump(const NormalizedConstraint &N) { + TD.AddChild([&] { Traverse(N); }); + } + +private: + void Traverse(const NormalizedConstraint &N) { + switch (N.getKind()) { + case NormalizedConstraint::ConstraintKind::Compound: + VisitCompound(static_cast<const CompoundConstraint &>(N)); + break; + case NormalizedConstraint::ConstraintKind::Atomic: + VisitAtomic(static_cast<const AtomicConstraint &>(N)); + break; + case NormalizedConstraint::ConstraintKind::ConceptId: + VisitConceptId(static_cast<const ConceptIdConstraint &>(N)); + break; + case NormalizedConstraint::ConstraintKind::FoldExpanded: + VisitFoldExpanded(static_cast<const FoldExpandedConstraint &>(N)); + break; + } + } + + void WriteNodeHeader(const NormalizedConstraint &N, StringRef Kind) { + OS << Kind; + TD.dumpPointer(&N); + TD.dumpSourceRange(N.getSourceRange()); + } + + void WritePackIndex(const NormalizedConstraintWithParamMapping &N) { + if (auto Idx = N.getPackSubstitutionIndex()) + OS << " SubstIndex=" << *Idx; + } + + void VisitCompound(const CompoundConstraint &C) { + WriteNodeHeader(C, "CompoundConstraint"); + OS << " " + << (C.getCompoundKind() == NormalizedConstraint::CCK_Conjunction + ? "Conjunction" + : "Disjunction"); + TD.AddChild([&] { Traverse(C.getLHS()); }); + TD.AddChild([&] { Traverse(C.getRHS()); }); + } + + void VisitAtomic(const AtomicConstraint &A) { + WriteNodeHeader(A, "AtomicConstraint"); + WritePackIndex(A); + OS << " "; + A.getConstraintExpr()->printPretty(OS, /*Helper=*/nullptr, PP); + WriteParameterMapping(A); + } + + void VisitConceptId(const ConceptIdConstraint &C) { + WriteNodeHeader(C, "ConceptIdConstraint"); + WritePackIndex(C); + OS << " "; + if (auto *CSE = C.getConceptSpecializationExpr()) { + CSE->printPretty(OS, /*Helper=*/nullptr, PP); + } else { + C.getConceptId()->print(OS, PP); + } + WriteParameterMapping(C); + TD.AddChild([&] { Traverse(C.getNormalizedConstraint()); }); + } + + void VisitFoldExpanded(const FoldExpandedConstraint &F) { + WriteNodeHeader(F, "FoldExpandedConstraint"); + OS << " " + << (F.getFoldOperator() == FoldExpandedConstraint::FoldOperatorKind::And + ? "And" + : "Or"); + WritePackIndex(F); + OS << " "; + F.getPattern()->printPretty(OS, /*Helper=*/nullptr, PP); + WriteParameterMapping(F); + TD.AddChild([&] { Traverse(F.getNormalizedPattern()); }); + } + + void WriteParameterMapping(const NormalizedConstraintWithParamMapping &N) { + if (!N.hasParameterMapping() || N.mappingOccurenceList().none()) + return; + TD.AddChild([this, Indexes(N.mappingOccurenceList()), + IndexesForSub(N.mappingOccurenceListForSubsumption()), + Mapping(N.getParameterMapping()), + TPL(N.getUsedTemplateParamList())] { + OS << "ParameterMapping"; + WriteOccurenceList("Indexes", Indexes); + WriteOccurenceList("IndexesForSubsumption", IndexesForSub); + unsigned Slot = 0; + for (unsigned ParamIndex : Indexes.set_bits()) { + TD.AddChild([this, Slot, ParamIndex, Mapping, TPL] { + OS << "#" << ParamIndex << ": "; + if (TPL && Slot < TPL->size()) { + const NamedDecl *Param = TPL->getParam(Slot); + OS << "<"; + Param->print(OS, PP); + OS << ">"; + } + OS << " -> "; + Mapping[Slot].getArgument().print(PP, OS, + /*IncludeType=*/false); + TD.AddChild([this, Slot, Mapping] { + const TemplateArgument &TA = Mapping[Slot].getArgument(); + OS << "TemplateArgument " << TA.getKindName(); + TD.dumpPointer(&TA); + }); + }); + ++Slot; + } + }); + } + + void WriteOccurenceList(StringRef Label, + const NormalizedConstraint::OccurenceList &BV) { + if (BV.none()) + return; + OS << " " << Label << "={" + << llvm::join( + llvm::map_range( + llvm::make_range(BV.set_bits_begin(), BV.set_bits_end()), + [](unsigned I) { return llvm::to_string(I); }), + ", ") + << '}'; + } +}; + +} // namespace + +LLVM_DUMP_METHOD void NormalizedConstraint::dump(ASTContext &Context) const { + dump(llvm::errs(), Context); +} + +LLVM_DUMP_METHOD void NormalizedConstraint::dump(llvm::raw_ostream &OS, + ASTContext &Context) const { + return DumpNormalizedConstraint(OS, Context).dump(*this); +} >From 96efa569ed147b31c75b5db3a18036d718d2c539 Mon Sep 17 00:00:00 2001 From: Younan Zhang <[email protected]> Date: Mon, 20 Jul 2026 19:31:05 +0800 Subject: [PATCH 2/2] Simplify a bit --- clang/lib/Sema/SemaConcept.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 98d3951c491b0..a1a2e08da1d32 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -3070,14 +3070,11 @@ class DumpNormalizedConstraint { unsigned Slot = 0; for (unsigned ParamIndex : Indexes.set_bits()) { TD.AddChild([this, Slot, ParamIndex, Mapping, TPL] { - OS << "#" << ParamIndex << ": "; - if (TPL && Slot < TPL->size()) { - const NamedDecl *Param = TPL->getParam(Slot); - OS << "<"; - Param->print(OS, PP); - OS << ">"; - } - OS << " -> "; + assert(TPL && Slot < TPL->size()); + const NamedDecl *Param = TPL->getParam(Slot); + OS << "#" << ParamIndex << ": <"; + Param->print(OS, PP); + OS << "> -> "; Mapping[Slot].getArgument().print(PP, OS, /*IncludeType=*/false); TD.AddChild([this, Slot, Mapping] { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
