https://github.com/cor3ntin updated https://github.com/llvm/llvm-project/pull/217637
>From 48a31aad53a8ed58da9fd216232580f4260fafc9 Mon Sep 17 00:00:00 2001 From: Corentin Jabot <[email protected]> Date: Thu, 20 Aug 2026 15:13:02 +0200 Subject: [PATCH 1/2] [Clang] use TemplateName in AutoType / TypeConstraint to store a concept. This is in preparation of implementing P3670 - ie we are going to have pack indexing to model a concept, so a TemplateDecl* is not sufficient. This is fairly mechanical. There are still some places, especially in tooling & json dumping where we reach to the underlying TemplateDecl - which will have to change later. But I think we need to have pack insdexing first to update these places. The serialization of AutoType was changed to work around a weirdness of TemplateName which makes serialization of an null TemplateName impossible. --- clang-tools-extra/clang-doc/Serialize.cpp | 8 ++-- clang-tools-extra/clangd/DumpAST.cpp | 2 +- clang-tools-extra/clangd/FindTarget.cpp | 4 +- clang/include/clang/AST/ASTConcept.h | 12 +++--- clang/include/clang/AST/ASTContext.h | 2 +- clang/include/clang/AST/ExprConcepts.h | 6 ++- clang/include/clang/AST/TextNodeDumper.h | 1 + clang/include/clang/AST/TypeBase.h | 12 +++--- clang/include/clang/AST/TypeLoc.h | 4 +- clang/include/clang/AST/TypeProperties.td | 11 +++-- clang/include/clang/ExtractAPI/API.h | 18 +++++++-- clang/lib/AST/ASTConcept.cpp | 2 +- clang/lib/AST/ASTContext.cpp | 40 ++++++++++--------- clang/lib/AST/ASTDumper.cpp | 2 +- clang/lib/AST/ASTImporter.cpp | 14 ++++--- clang/lib/AST/ASTStructuralEquivalence.cpp | 4 +- clang/lib/AST/ItaniumMangle.cpp | 15 +++---- clang/lib/AST/JSONNodeDumper.cpp | 3 +- clang/lib/AST/ODRHash.cpp | 2 +- clang/lib/AST/StmtPrinter.cpp | 2 +- clang/lib/AST/StmtProfile.cpp | 2 +- clang/lib/AST/TextNodeDumper.cpp | 28 ++++++++++--- clang/lib/AST/Type.cpp | 17 +++----- clang/lib/AST/TypeLoc.cpp | 6 +-- clang/lib/AST/TypePrinter.cpp | 10 +++-- clang/lib/ExtractAPI/DeclarationFragments.cpp | 1 + clang/lib/Index/IndexBody.cpp | 6 +-- clang/lib/Index/IndexDecl.cpp | 5 ++- clang/lib/Index/IndexTypeSourceInfo.cpp | 2 +- clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp | 4 +- clang/lib/Sema/SemaChecking.cpp | 3 +- clang/lib/Sema/SemaCodeComplete.cpp | 4 +- clang/lib/Sema/SemaConcept.cpp | 25 +++++++----- clang/lib/Sema/SemaTemplate.cpp | 21 +++++----- clang/lib/Sema/SemaTemplateDeduction.cpp | 11 +++-- clang/lib/Sema/SemaTemplateInstantiate.cpp | 5 +-- clang/lib/Sema/SemaType.cpp | 33 ++++++++------- clang/lib/Sema/TreeTransform.h | 20 ++++++---- clang/lib/Serialization/ASTReader.cpp | 2 +- clang/lib/Serialization/ASTWriter.cpp | 2 +- clang/tools/libclang/CIndex.cpp | 14 +++---- 41 files changed, 218 insertions(+), 167 deletions(-) diff --git a/clang-tools-extra/clang-doc/Serialize.cpp b/clang-tools-extra/clang-doc/Serialize.cpp index 5fa23416949c4..e490ae1d08bfb 100644 --- a/clang-tools-extra/clang-doc/Serialize.cpp +++ b/clang-tools-extra/clang-doc/Serialize.cpp @@ -842,8 +842,8 @@ void Serializer::handleCompoundConstraints( } else if (Constraint->getStmtClass() == Stmt::ConceptSpecializationExprClass) { auto *Concept = dyn_cast<ConceptSpecializationExpr>(Constraint); - ConstraintInfo CI(getUSRForDecl(Concept->getNamedConcept()), - Concept->getNamedConcept()->getNameAsString()); + ConstraintInfo CI(getUSRForDecl(Concept->getConceptDecl()), + Concept->getConceptDecl()->getNameAsString()); CI.ConstraintExpr = internString(exprToString(Concept)); ConstraintInfos.push_back(CI); } @@ -864,8 +864,8 @@ void Serializer::populateConstraints(TemplateInfo &I, const TemplateDecl *D) { if (const auto *ConstraintExpr = dyn_cast_or_null<ConceptSpecializationExpr>( Constraint.ConstraintExpr)) { - ConstraintInfo CI(getUSRForDecl(ConstraintExpr->getNamedConcept()), - ConstraintExpr->getNamedConcept()->getNameAsString()); + ConstraintInfo CI(getUSRForDecl(ConstraintExpr->getConceptDecl()), + ConstraintExpr->getConceptDecl()->getNameAsString()); CI.ConstraintExpr = internString(exprToString(ConstraintExpr)); LocalConstraints.push_back(std::move(CI)); } else { diff --git a/clang-tools-extra/clangd/DumpAST.cpp b/clang-tools-extra/clangd/DumpAST.cpp index 2b673128493b3..2bcbbc09d90fe 100644 --- a/clang-tools-extra/clangd/DumpAST.cpp +++ b/clang-tools-extra/clangd/DumpAST.cpp @@ -303,7 +303,7 @@ class DumpVisitor : public RecursiveASTVisitor<DumpVisitor> { return CBS.isVirtual() ? "virtual" : ""; } std::string getDetail(const ConceptReference *CR) { - return CR->getNamedConcept()->getNameAsString(); + return CR->getNamedConcept().getAsTemplateDecl()->getNameAsString(); } /// Arcana is produced by TextNodeDumper, for the types it supports. diff --git a/clang-tools-extra/clangd/FindTarget.cpp b/clang-tools-extra/clangd/FindTarget.cpp index 41c9cddfebbbc..aea04e14b2cf8 100644 --- a/clang-tools-extra/clangd/FindTarget.cpp +++ b/clang-tools-extra/clangd/FindTarget.cpp @@ -519,7 +519,7 @@ struct TargetFinder { } void add(const ConceptReference *CR, RelSet Flags) { - add(CR->getNamedConcept(), Flags); + add(CR->getNamedConcept().getAsTemplateDecl(), Flags); } }; @@ -1081,7 +1081,7 @@ class ExplicitReferenceCollector return {ReferenceLoc{CR->getNestedNameSpecifierLoc(), CR->getConceptNameLoc(), /*IsDecl=*/false, - {CR->getNamedConcept()}}}; + {CR->getNamedConcept().getAsTemplateDecl()}}}; if (const OffsetOfNode *OON = N.get<OffsetOfNode>()) { if (OON->getKind() == OffsetOfNode::Field) return {ReferenceLoc{NestedNameSpecifierLoc(), diff --git a/clang/include/clang/AST/ASTConcept.h b/clang/include/clang/AST/ASTConcept.h index 4319df35ab7e5..9a65c32b5ca1e 100644 --- a/clang/include/clang/AST/ASTConcept.h +++ b/clang/include/clang/AST/ASTConcept.h @@ -146,7 +146,7 @@ class ConceptReference { NamedDecl *FoundDecl; /// \brief The concept named. - TemplateDecl *NamedConcept; + TemplateName NamedConcept; /// \brief The template argument list source info used to specialize the /// concept. @@ -154,7 +154,7 @@ class ConceptReference { ConceptReference(NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl, - TemplateDecl *NamedConcept, + TemplateName NamedConcept, const ASTTemplateArgumentListInfo *ArgsAsWritten) : NestedNameSpec(NNS), TemplateKWLoc(TemplateKWLoc), ConceptName(ConceptNameInfo), FoundDecl(FoundDecl), @@ -164,7 +164,7 @@ class ConceptReference { static ConceptReference * Create(const ASTContext &C, NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo, - NamedDecl *FoundDecl, TemplateDecl *NamedConcept, + NamedDecl *FoundDecl, TemplateName NamedConcept, const ASTTemplateArgumentListInfo *ArgsAsWritten); const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const { @@ -198,7 +198,7 @@ class ConceptReference { return FoundDecl; } - TemplateDecl *getNamedConcept() const { return NamedConcept; } + TemplateName getNamedConcept() const { return NamedConcept; } const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { return ArgsAsWritten; @@ -251,9 +251,7 @@ class TypeConstraint { // FIXME: Instead of using these concept related functions the callers should // directly work with the corresponding ConceptReference. - TemplateDecl *getNamedConcept() const { - return ConceptRef->getNamedConcept(); - } + TemplateName getNamedConcept() const { return ConceptRef->getNamedConcept(); } SourceLocation getConceptNameLoc() const { return ConceptRef->getConceptNameLoc(); diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 56b51566f58f5..0539149105633 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -2155,7 +2155,7 @@ class ASTContext : public RefCountedBase<ASTContext> { /// C++11 deduced auto type. QualType getAutoType(DeducedKind DK, QualType DeducedAsType, AutoTypeKeyword Keyword, - TemplateDecl *TypeConstraintConcept = nullptr, + TemplateName TypeConstraintConcept = TemplateName(), ArrayRef<TemplateArgument> TypeConstraintArgs = {}) const; /// C++11 deduction pattern for 'auto' type. diff --git a/clang/include/clang/AST/ExprConcepts.h b/clang/include/clang/AST/ExprConcepts.h index 4f162b6ffc8af..18ce5a94ebef3 100644 --- a/clang/include/clang/AST/ExprConcepts.h +++ b/clang/include/clang/AST/ExprConcepts.h @@ -84,8 +84,10 @@ class ConceptSpecializationExpr final : public Expr { ConceptReference *getConceptReference() const { return ConceptRef; } - ConceptDecl *getNamedConcept() const { - return cast<ConceptDecl>(ConceptRef->getNamedConcept()); + TemplateName getNamedConcept() const { return ConceptRef->getNamedConcept(); } + + ConceptDecl *getConceptDecl() const { + return cast<ConceptDecl>(getNamedConcept().getAsTemplateDecl()); } // FIXME: Several of the following functions can be removed. Instead the diff --git a/clang/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h index 5d4a4456b40a1..1cdd8c37c7fc6 100644 --- a/clang/include/clang/AST/TextNodeDumper.h +++ b/clang/include/clang/AST/TextNodeDumper.h @@ -216,6 +216,7 @@ class TextNodeDumper void dumpConceptReference(const ConceptReference *R); void dumpTemplateArgument(const TemplateArgument &TA); void dumpBareTemplateName(TemplateName TN); + void dumpBareConcept(TemplateName TN); void dumpTemplateName(TemplateName TN, StringRef Label = {}); void dumpDeclRef(const Decl *D, StringRef Label = {}); diff --git a/clang/include/clang/AST/TypeBase.h b/clang/include/clang/AST/TypeBase.h index eb05a068934ea..12bfd192287d7 100644 --- a/clang/include/clang/AST/TypeBase.h +++ b/clang/include/clang/AST/TypeBase.h @@ -7381,10 +7381,10 @@ class DeducedType : public Type { class AutoType : public DeducedType, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these - TemplateDecl *TypeConstraintConcept; + TemplateName TypeConstraintConcept; AutoType(DeducedKind DK, QualType DeducedAsTypeOrCanon, - AutoTypeKeyword Keyword, TemplateDecl *TypeConstraintConcept, + AutoTypeKeyword Keyword, TemplateName TypeConstraintConcept, ArrayRef<TemplateArgument> TypeConstraintArgs); public: @@ -7393,13 +7393,11 @@ class AutoType : public DeducedType, public llvm::FoldingSetNode { AutoTypeBits.NumArgs}; } - TemplateDecl *getTypeConstraintConcept() const { + TemplateName getTypeConstraintConcept() const { return TypeConstraintConcept; } - bool isConstrained() const { - return TypeConstraintConcept != nullptr; - } + bool isConstrained() const { return !TypeConstraintConcept.isNull(); } bool isDecltypeAuto() const { return getKeyword() == AutoTypeKeyword::DecltypeAuto; @@ -7416,7 +7414,7 @@ class AutoType : public DeducedType, public llvm::FoldingSetNode { void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context); static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, DeducedKind DK, QualType Deduced, AutoTypeKeyword Keyword, - TemplateDecl *CD, ArrayRef<TemplateArgument> Arguments); + TemplateName CD, ArrayRef<TemplateArgument> Arguments); static bool classof(const Type *T) { return T->getTypeClass() == Auto; diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h index 2648806ac687a..b3cb4d0f33629 100644 --- a/clang/include/clang/AST/TypeLoc.h +++ b/clang/include/clang/AST/TypeLoc.h @@ -2463,10 +2463,10 @@ class AutoTypeLoc return nullptr; } - TemplateDecl *getNamedConcept() const { + TemplateName getNamedConcept() const { if (const auto *CR = getConceptReference()) return CR->getNamedConcept(); - return nullptr; + return TemplateName(); } DeclarationNameInfo getConceptNameInfo() const { diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td index 1723fed7bfd91..5b3966db9001b 100644 --- a/clang/include/clang/AST/TypeProperties.td +++ b/clang/include/clang/AST/TypeProperties.td @@ -531,9 +531,12 @@ let Class = AutoType in { def : Property<"keyword", AutoTypeKeyword> { let Read = [{ node->getKeyword() }]; } - def : Property<"typeConstraintConcept", Optional<TemplateDeclRef>> { - let Read = [{ makeOptionalFromPointer( - node->getTypeConstraintConcept()) }]; + def : Property<"isConstrained", Bool> { + let Read = [{ node->isConstrained() }]; + } + def : Property<"typeConstraintConcept", TemplateName> { + let Conditional = [{ isConstrained }]; + let Read = [{ node->getTypeConstraintConcept() }]; } def : Property<"typeConstraintArguments", Array<TemplateArgument>> { let Read = [{ node->getTypeConstraintArguments() }]; @@ -541,7 +544,7 @@ let Class = AutoType in { def : Creator<[{ return ctx.getAutoType(deducedKind, makeNullableFromOptional(deducedType), keyword, - makePointerFromOptional(typeConstraintConcept), + isConstrained ? *typeConstraintConcept : TemplateName(), typeConstraintArguments); }]>; } diff --git a/clang/include/clang/ExtractAPI/API.h b/clang/include/clang/ExtractAPI/API.h index 62483bcf2cdc9..d0d05fcab4af6 100644 --- a/clang/include/clang/ExtractAPI/API.h +++ b/clang/include/clang/ExtractAPI/API.h @@ -71,7 +71,11 @@ class Template { continue; std::string Type; if (Param->hasTypeConstraint()) - Type = Param->getTypeConstraint()->getNamedConcept()->getName().str(); + Type = Param->getTypeConstraint() + ->getNamedConcept() + .getAsTemplateDecl() + ->getName() + .str(); else if (Param->wasDeclaredWithTypename()) Type = "typename"; else @@ -89,7 +93,11 @@ class Template { continue; std::string Type; if (Param->hasTypeConstraint()) - Type = Param->getTypeConstraint()->getNamedConcept()->getName().str(); + Type = Param->getTypeConstraint() + ->getNamedConcept() + .getAsTemplateDecl() + ->getName() + .str(); else if (Param->wasDeclaredWithTypename()) Type = "typename"; else @@ -107,7 +115,11 @@ class Template { continue; std::string Type; if (Param->hasTypeConstraint()) - Type = Param->getTypeConstraint()->getNamedConcept()->getName().str(); + Type = Param->getTypeConstraint() + ->getNamedConcept() + .getAsTemplateDecl() + ->getName() + .str(); else if (Param->wasDeclaredWithTypename()) Type = "typename"; else diff --git a/clang/lib/AST/ASTConcept.cpp b/clang/lib/AST/ASTConcept.cpp index fd12bc4e83827..c843aa797f9ba 100644 --- a/clang/lib/AST/ASTConcept.cpp +++ b/clang/lib/AST/ASTConcept.cpp @@ -93,7 +93,7 @@ ConceptReference * ConceptReference::Create(const ASTContext &C, NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo, - NamedDecl *FoundDecl, TemplateDecl *NamedConcept, + NamedDecl *FoundDecl, TemplateName NamedConcept, const ASTTemplateArgumentListInfo *ArgsAsWritten) { return new (C) ConceptReference(NNS, TemplateKWLoc, ConceptNameInfo, FoundDecl, NamedConcept, ArgsAsWritten); diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 35a2a0b131a3f..df6d03b4f17ed 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -6912,10 +6912,10 @@ ASTContext::getUnaryTransformType(QualType BaseType, QualType UnderlyingType, QualType ASTContext::getAutoType(DeducedKind DK, QualType DeducedAsType, AutoTypeKeyword Keyword, - TemplateDecl *TypeConstraintConcept, + TemplateName TypeConstraintConcept, ArrayRef<TemplateArgument> TypeConstraintArgs) const { if (DK == DeducedKind::Undeduced && Keyword == AutoTypeKeyword::Auto && - !TypeConstraintConcept) { + TypeConstraintConcept.isNull()) { assert(DeducedAsType.isNull() && ""); assert(TypeConstraintArgs.empty() && ""); return getAutoDeductType(); @@ -6932,10 +6932,10 @@ ASTContext::getAutoType(DeducedKind DK, QualType DeducedAsType, assert(!DeducedAsType.isNull() && "deduced type must be provided"); } else { assert(DeducedAsType.isNull() && "deduced type must not be provided"); - if (TypeConstraintConcept) { + if (!TypeConstraintConcept.isNull()) { bool AnyNonCanonArgs = false; - auto *CanonicalConcept = - cast<TemplateDecl>(TypeConstraintConcept->getCanonicalDecl()); + TemplateName CanonicalConcept = + getCanonicalTemplateName(TypeConstraintConcept); auto CanonicalConceptArgs = ::getCanonicalTemplateArguments( *this, TypeConstraintArgs, AnyNonCanonArgs); if (TypeConstraintConcept != CanonicalConcept || AnyNonCanonArgs) @@ -7056,12 +7056,12 @@ QualType ASTContext::getAtomicType(QualType T) const { /// getAutoDeductType - Get type pattern for deducing against 'auto'. QualType ASTContext::getAutoDeductType() const { if (AutoDeductTy.isNull()) - AutoDeductTy = QualType(new (*this, alignof(AutoType)) - AutoType(DeducedKind::Undeduced, QualType(), - AutoTypeKeyword::Auto, - /*TypeConstraintConcept=*/nullptr, - /*TypeConstraintArgs=*/{}), - 0); + AutoDeductTy = QualType( + new (*this, alignof(AutoType)) + AutoType(DeducedKind::Undeduced, QualType(), AutoTypeKeyword::Auto, + /*TypeConstraintConcept=*/TemplateName(), + /*TypeConstraintArgs=*/{}), + 0); return AutoDeductTy; } @@ -7555,8 +7555,8 @@ bool ASTContext::isSameTypeConstraint(const TypeConstraint *XTC, if (!XTC) return true; - auto *NCX = XTC->getNamedConcept(); - auto *NCY = YTC->getNamedConcept(); + TemplateDecl *NCX = XTC->getNamedConcept().getAsTemplateDecl(); + TemplateDecl *NCY = YTC->getNamedConcept().getAsTemplateDecl(); if (!NCX || !NCY || !isSameEntity(NCX, NCY)) return false; if (XTC->getConceptReference()->hasExplicitTemplateArgs() != @@ -14442,8 +14442,9 @@ static QualType getCommonNonSugarTypeNode(const ASTContext &Ctx, const Type *X, assert(AX->getDeducedKind() == AY->getDeducedKind()); assert(AX->getDeducedKind() != DeducedKind::Deduced); assert(AX->getKeyword() == AY->getKeyword()); - TemplateDecl *CD = ::getCommonDecl(AX->getTypeConstraintConcept(), - AY->getTypeConstraintConcept()); + TemplateDecl *CD = + ::getCommonDecl(AX->getTypeConstraintConcept().getAsTemplateDecl(), + AY->getTypeConstraintConcept().getAsTemplateDecl()); SmallVector<TemplateArgument, 8> As; if (CD && getCommonTemplateArguments(Ctx, As, AX->getTypeConstraintArguments(), @@ -14452,7 +14453,7 @@ static QualType getCommonNonSugarTypeNode(const ASTContext &Ctx, const Type *X, As.clear(); } return Ctx.getAutoType(AX->getDeducedKind(), QualType(), AX->getKeyword(), - CD, As); + TemplateName(CD), As); } case Type::IncompleteArray: { const auto *AX = cast<IncompleteArrayType>(X), @@ -14833,8 +14834,9 @@ static QualType getCommonSugarTypeNode(const ASTContext &Ctx, const Type *X, if (KW != AY->getKeyword()) return QualType(); - TemplateDecl *CD = ::getCommonDecl(AX->getTypeConstraintConcept(), - AY->getTypeConstraintConcept()); + TemplateDecl *CD = + ::getCommonDecl(AX->getTypeConstraintConcept().getAsTemplateDecl(), + AY->getTypeConstraintConcept().getAsTemplateDecl()); SmallVector<TemplateArgument, 8> As; if (CD && getCommonTemplateArguments(Ctx, As, AX->getTypeConstraintArguments(), @@ -14847,7 +14849,7 @@ static QualType getCommonSugarTypeNode(const ASTContext &Ctx, const Type *X, // sugar. This implies they can't contain unexpanded packs either. return Ctx.getAutoType(DeducedKind::Deduced, Ctx.getQualifiedType(Underlying), AX->getKeyword(), - CD, As); + TemplateName(CD), As); } case Type::PackIndexing: case Type::Decltype: diff --git a/clang/lib/AST/ASTDumper.cpp b/clang/lib/AST/ASTDumper.cpp index 146fc5ea5caad..f74fec07b6175 100644 --- a/clang/lib/AST/ASTDumper.cpp +++ b/clang/lib/AST/ASTDumper.cpp @@ -362,7 +362,7 @@ LLVM_DUMP_METHOD void ConceptReference::dump() const { } LLVM_DUMP_METHOD void ConceptReference::dump(raw_ostream &OS) const { - auto &Ctx = getNamedConcept()->getASTContext(); + auto &Ctx = getNamedConcept().getAsTemplateDecl()->getASTContext(); ASTDumper P(OS, Ctx, showColorsForStream(Ctx, OS)); P.Visit(this); } diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index c2164352126ef..69f50bce925a0 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -1748,10 +1748,14 @@ ExpectedType ASTNodeImporter::VisitAutoType(const AutoType *T) { if (!ToDeducedTypeOrErr) return ToDeducedTypeOrErr.takeError(); - Expected<TemplateDecl *> ToTypeConstraint = - import(T->getTypeConstraintConcept()); - if (!ToTypeConstraint) - return ToTypeConstraint.takeError(); + TemplateName ToTypeConstraint; + if (TemplateName FromTypeConstraint = T->getTypeConstraintConcept(); + !FromTypeConstraint.isNull()) { + Expected<TemplateName> ToTypeConstraintOrErr = import(FromTypeConstraint); + if (!ToTypeConstraintOrErr) + return ToTypeConstraintOrErr.takeError(); + ToTypeConstraint = *ToTypeConstraintOrErr; + } SmallVector<TemplateArgument, 2> ToTemplateArgs; if (Error Err = ImportTemplateArguments(T->getTypeConstraintArguments(), @@ -1760,7 +1764,7 @@ ExpectedType ASTNodeImporter::VisitAutoType(const AutoType *T) { return Importer.getToContext().getAutoType( T->getDeducedKind(), *ToDeducedTypeOrErr, T->getKeyword(), - *ToTypeConstraint, ToTemplateArgs); + ToTypeConstraint, ToTemplateArgs); } ExpectedType ASTNodeImporter::VisitDeducedTemplateSpecializationType( diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index ebf4507e6e67d..d6d527f0641a3 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -1340,8 +1340,8 @@ bool ASTStructuralEquivalence::isEquivalent( if (Auto1->isConstrained() != Auto2->isConstrained()) return false; if (Auto1->isConstrained()) { - if (Auto1->getTypeConstraintConcept() != - Auto2->getTypeConstraintConcept()) + if (Auto1->getTypeConstraintConcept().getAsTemplateDecl() != + Auto2->getTypeConstraintConcept().getAsTemplateDecl()) return false; if (!IsStructurallyEquivalent(Context, Auto1->getTypeConstraintArguments(), diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index c77d9d979e932..7528aa1b9bbcd 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -518,7 +518,7 @@ class CXXNameMangler { void mangleUnqualifiedBlock(const BlockDecl *Block); void mangleTemplateParamDecl(const NamedDecl *Decl); void mangleTemplateParameterList(const TemplateParameterList *Params); - void mangleTypeConstraint(const TemplateDecl *Concept, + void mangleTypeConstraint(TemplateName Concept, ArrayRef<TemplateArgument> Arguments); void mangleTypeConstraint(const TypeConstraint *Constraint); void mangleRequiresClause(const Expr *RequiresClause); @@ -2095,14 +2095,15 @@ void CXXNameMangler::mangleTemplateParameterList( } void CXXNameMangler::mangleTypeConstraint( - const TemplateDecl *Concept, ArrayRef<TemplateArgument> Arguments) { - const DeclContext *DC = Context.getEffectiveDeclContext(Concept); + TemplateName Concept, ArrayRef<TemplateArgument> Arguments) { + const TemplateDecl *TD = Concept.getAsTemplateDecl(); + const DeclContext *DC = Context.getEffectiveDeclContext(TD); if (!Arguments.empty()) - mangleTemplateName(Concept, Arguments); + mangleTemplateName(TD, Arguments); else if (DC->isTranslationUnit() || isStdNamespace(DC)) - mangleUnscopedName(Concept, DC); + mangleUnscopedName(TD, DC); else - mangleNestedName(Concept, DC); + mangleNestedName(TD, DC); } void CXXNameMangler::mangleTypeConstraint(const TypeConstraint *Constraint) { @@ -5710,7 +5711,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity, // entity, meaning that references to enclosing template arguments don't // work. Out << "L_Z"; - mangleTemplateName(CSE->getNamedConcept(), CSE->getTemplateArguments()); + mangleTemplateName(CSE->getConceptDecl(), CSE->getTemplateArguments()); Out << 'E'; break; } diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp index b9c2272b97a4b..4cea437db4150 100644 --- a/clang/lib/AST/JSONNodeDumper.cpp +++ b/clang/lib/AST/JSONNodeDumper.cpp @@ -241,7 +241,8 @@ void JSONNodeDumper::Visit(const APValue &Value, QualType Ty) { void JSONNodeDumper::Visit(const ConceptReference *CR) { JOS.attribute("kind", "ConceptReference"); - JOS.attribute("id", createPointerRepresentation(CR->getNamedConcept())); + JOS.attribute("id", createPointerRepresentation( + CR->getNamedConcept().getAsTemplateDecl())); if (const auto *Args = CR->getTemplateArgsAsWritten()) { JOS.attributeArray("templateArgsAsWritten", [Args, this] { for (const TemplateArgumentLoc &TAL : Args->arguments()) diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp index 297d6ba5b7686..386979d0f9ce2 100644 --- a/clang/lib/AST/ODRHash.cpp +++ b/clang/lib/AST/ODRHash.cpp @@ -1039,7 +1039,7 @@ class ODRTypeVisitor : public TypeVisitor<ODRTypeVisitor> { ID.AddInteger((unsigned)T->getKeyword()); ID.AddInteger(T->isConstrained()); if (T->isConstrained()) { - AddDecl(T->getTypeConstraintConcept()); + Hash.AddTemplateName(T->getTypeConstraintConcept()); ID.AddInteger(T->getTypeConstraintArguments().size()); for (const auto &TA : T->getTypeConstraintArguments()) Hash.AddTemplateArgument(TA); diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index e08566e5ae011..e957b03b7e898 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -2793,7 +2793,7 @@ void StmtPrinter::VisitConceptSpecializationExpr(ConceptSpecializationExpr *E) { OS << E->getFoundDecl()->getName(); printTemplateArgumentList(OS, E->getTemplateArgsAsWritten()->arguments(), Policy, - E->getNamedConcept()->getTemplateParameters()); + E->getConceptDecl()->getTemplateParameters()); } void StmtPrinter::VisitRequiresExpr(RequiresExpr *E) { diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index dca2c49ac45d5..08b42c1477664 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -1775,7 +1775,7 @@ void StmtProfiler::VisitAtomicExpr(const AtomicExpr *S) { void StmtProfiler::VisitConceptSpecializationExpr( const ConceptSpecializationExpr *S) { VisitExpr(S); - VisitDecl(S->getNamedConcept()); + VisitTemplateName(S->getNamedConcept()); for (const TemplateArgument &Arg : S->getTemplateArguments()) VisitTemplateArgument(Arg); } diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp index 55e71cf58f248..f58cc4f5761b7 100644 --- a/clang/lib/AST/TextNodeDumper.cpp +++ b/clang/lib/AST/TextNodeDumper.cpp @@ -555,7 +555,7 @@ void TextNodeDumper::Visit(const ConceptReference *R) { dumpPointer(R); dumpSourceRange(R->getSourceRange()); OS << ' '; - dumpBareDeclRef(R->getNamedConcept()); + dumpBareConcept(R->getNamedConcept()); } void TextNodeDumper::Visit(const concepts::Requirement *R) { @@ -957,6 +957,21 @@ void TextNodeDumper::dumpType(QualType T) { dumpBareType(T); } +void TextNodeDumper::dumpBareConcept(TemplateName TN) { + { + ColorScope Color(OS, ShowColors, ASTDumpColor::DeclKindName); + OS << "Concept"; + } + + const TemplateDecl *TD = TN.getAsTemplateDecl(); + dumpPointer(TD); + + ColorScope Color(OS, ShowColors, ASTDumpColor::DeclName); + OS << " '"; + OS << TD->getDeclName(); + OS << '\''; +} + void TextNodeDumper::dumpBareDeclRef(const Decl *D) { if (!D) { ColorScope Color(OS, ShowColors, ASTDumpColor::Null); @@ -2317,7 +2332,7 @@ void TextNodeDumper::VisitAutoType(const AutoType *T) { // Not necessary to dump the keyword since it's spelled plainly in the printed // type anyway. if (T->isConstrained()) - dumpDeclRef(T->getTypeConstraintConcept()); + AddChild([=] { dumpBareConcept(T->getTypeConstraintConcept()); }); } void TextNodeDumper::VisitDeducedTemplateSpecializationType( @@ -2931,11 +2946,12 @@ void TextNodeDumper::VisitBuiltinTemplateDecl(const BuiltinTemplateDecl *D) { void TextNodeDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { if (const auto *TC = D->getTypeConstraint()) { - OS << " "; - dumpBareDeclRef(TC->getNamedConcept()); - if (TC->getNamedConcept() != TC->getFoundDecl()) { + OS << ' '; + dumpBareConcept(TC->getNamedConcept()); + if (const auto *USD = + dyn_cast_if_present<UsingShadowDecl>(TC->getFoundDecl())) { OS << " ("; - dumpBareDeclRef(TC->getFoundDecl()); + dumpBareDeclRef(USD); OS << ")"; } } else if (D->wasDeclaredWithTypename()) diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index 4063d03f7750e..fa346856a260c 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -5740,20 +5740,15 @@ DeducedType::DeducedType(TypeClass TC, DeducedKind DK, } AutoType::AutoType(DeducedKind DK, QualType DeducedAsTypeOrCanon, - AutoTypeKeyword Keyword, TemplateDecl *TypeConstraintConcept, + AutoTypeKeyword Keyword, TemplateName TypeConstraintConcept, ArrayRef<TemplateArgument> TypeConstraintArgs) : DeducedType(Auto, DK, DeducedAsTypeOrCanon) { AutoTypeBits.Keyword = llvm::to_underlying(Keyword); AutoTypeBits.NumArgs = TypeConstraintArgs.size(); this->TypeConstraintConcept = TypeConstraintConcept; - assert(TypeConstraintConcept || AutoTypeBits.NumArgs == 0); - if (TypeConstraintConcept) { - auto Dep = TypeDependence::None; - if (const auto *TTP = - dyn_cast<TemplateTemplateParmDecl>(TypeConstraintConcept)) - Dep = TypeDependence::DependentInstantiation | - (TTP->isParameterPack() ? TypeDependence::UnexpandedPack - : TypeDependence::None); + assert(!TypeConstraintConcept.isNull() || AutoTypeBits.NumArgs == 0); + if (!TypeConstraintConcept.isNull()) { + auto Dep = toTypeDependence(TypeConstraintConcept.getDependence()); auto *ArgBuffer = const_cast<TemplateArgument *>(getTypeConstraintArguments().data()); @@ -5770,11 +5765,11 @@ AutoType::AutoType(DeducedKind DK, QualType DeducedAsTypeOrCanon, void AutoType::Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, DeducedKind DK, QualType Deduced, - AutoTypeKeyword Keyword, TemplateDecl *CD, + AutoTypeKeyword Keyword, TemplateName CD, ArrayRef<TemplateArgument> Arguments) { DeducedType::Profile(ID, DK, Deduced); ID.AddInteger(llvm::to_underlying(Keyword)); - ID.AddPointer(CD); + CD.Profile(ID); for (const TemplateArgument &Arg : Arguments) Arg.Profile(ID, Context); } diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp index e4bd490e5dd77..06406b805c402 100644 --- a/clang/lib/AST/TypeLoc.cpp +++ b/clang/lib/AST/TypeLoc.cpp @@ -767,9 +767,9 @@ void TemplateSpecializationTypeLoc::initializeArgLocs( static ConceptReference *createTrivialConceptReference(ASTContext &Context, SourceLocation Loc, const AutoType *AT) { - DeclarationNameInfo DNI = - DeclarationNameInfo(AT->getTypeConstraintConcept()->getDeclName(), Loc, - AT->getTypeConstraintConcept()->getDeclName()); + DeclarationName ConceptName = + AT->getTypeConstraintConcept().getAsTemplateDecl()->getDeclName(); + DeclarationNameInfo DNI = DeclarationNameInfo(ConceptName, Loc, ConceptName); unsigned size = AT->getTypeConstraintArguments().size(); llvm::SmallVector<TemplateArgumentLocInfo, 8> TALI(size); TemplateSpecializationTypeLoc::initializeArgLocs( diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index bb3aa2bd22e77..90d9e13a8646e 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -1412,12 +1412,14 @@ void TypePrinter::printAutoBefore(const AutoType *T, raw_ostream &OS) { if (T->isConstrained()) { // FIXME: Track a TypeConstraint as type sugar, so that we can print the // type as it was written. - T->getTypeConstraintConcept()->getDeclName().print(OS, Policy); + T->getTypeConstraintConcept().getAsTemplateDecl()->getDeclName().print( + OS, Policy); auto Args = T->getTypeConstraintArguments(); if (!Args.empty()) - printTemplateArgumentList( - OS, Args, Policy, - T->getTypeConstraintConcept()->getTemplateParameters()); + printTemplateArgumentList(OS, Args, Policy, + T->getTypeConstraintConcept() + .getAsTemplateDecl() + ->getTemplateParameters()); OS << ' '; } switch (T->getKeyword()) { diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp index 1ebaf2e7e2456..47b4b8c864a89 100644 --- a/clang/lib/ExtractAPI/DeclarationFragments.cpp +++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp @@ -1013,6 +1013,7 @@ DeclarationFragmentsBuilder::getFragmentsForTemplateParameters( if (TemplateParam->hasTypeConstraint()) Fragments.append(TemplateParam->getTypeConstraint() ->getNamedConcept() + .getAsTemplateDecl() ->getName() .str(), DeclarationFragments::FragmentKind::TypeIdentifier); diff --git a/clang/lib/Index/IndexBody.cpp b/clang/lib/Index/IndexBody.cpp index 1979117d4695c..e380d9c604492 100644 --- a/clang/lib/Index/IndexBody.cpp +++ b/clang/lib/Index/IndexBody.cpp @@ -500,14 +500,14 @@ class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> { } bool VisitConceptSpecializationExpr(ConceptSpecializationExpr *R) { - IndexCtx.handleReference(R->getNamedConcept(), R->getConceptNameLoc(), + IndexCtx.handleReference(R->getConceptDecl(), R->getConceptNameLoc(), Parent, ParentDC); return true; } bool TraverseTypeConstraint(const TypeConstraint *C) { - IndexCtx.handleReference(C->getNamedConcept(), C->getConceptNameLoc(), - Parent, ParentDC); + IndexCtx.handleReference(C->getNamedConcept().getAsTemplateDecl(), + C->getConceptNameLoc(), Parent, ParentDC); return RecursiveASTVisitor::TraverseTypeConstraint(C); } }; diff --git a/clang/lib/Index/IndexDecl.cpp b/clang/lib/Index/IndexDecl.cpp index 8b32a48483a67..311beb68a3daf 100644 --- a/clang/lib/Index/IndexDecl.cpp +++ b/clang/lib/Index/IndexDecl.cpp @@ -706,8 +706,9 @@ class IndexingDeclVisitor : public ConstDeclVisitor<IndexingDeclVisitor, bool> { handleTemplateArgumentLoc(TTP->getDefaultArgument(), Parent, TP->getLexicalDeclContext()); if (auto *C = TTP->getTypeConstraint()) - IndexCtx.handleReference(C->getNamedConcept(), C->getConceptNameLoc(), - Parent, TTP->getLexicalDeclContext()); + IndexCtx.handleReference(C->getNamedConcept().getAsTemplateDecl(), + C->getConceptNameLoc(), Parent, + TTP->getLexicalDeclContext()); } else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(TP)) { IndexCtx.indexTypeSourceInfo(NTTP->getTypeSourceInfo(), Parent); if (NTTP->hasDefaultArgument()) diff --git a/clang/lib/Index/IndexTypeSourceInfo.cpp b/clang/lib/Index/IndexTypeSourceInfo.cpp index c9ad36b5406c5..6f599ababcaf5 100644 --- a/clang/lib/Index/IndexTypeSourceInfo.cpp +++ b/clang/lib/Index/IndexTypeSourceInfo.cpp @@ -82,7 +82,7 @@ class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> { } bool VisitAutoTypeLoc(AutoTypeLoc TL) { - if (auto *C = TL.getNamedConcept()) + if (auto *C = TL.getNamedConcept().getAsTemplateDecl()) return IndexCtx.handleReference(C, TL.getConceptNameLoc(), Parent, ParentDC); return true; diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp index 5c17f0ebf6fdc..ab1dc5c6ff39c 100644 --- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp +++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp @@ -406,8 +406,8 @@ TemplateParameterListBuilder::constructConceptSpecializationExpr( // In the concept reference, ATALI is what adds the extra // TemplateArgument node underneath CSE - ConceptReference *CR = - ConceptReference::Create(Context, NNSLoc, Loc, DNI, CD, CD, ATALI); + ConceptReference *CR = ConceptReference::Create(Context, NNSLoc, Loc, DNI, CD, + TemplateName(CD), ATALI); ConceptSpecializationExpr *CSE = ConceptSpecializationExpr::Create(Context, CR, ImplicitCSEDecl, &CS); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 3e6266b8ac542..ff3d4b0a4b4c7 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -4723,7 +4723,8 @@ void Sema::checkCall(NamedDecl *FDecl, const FunctionProtoType *Proto, } void Sema::CheckConstrainedAuto(const AutoType *AutoT, SourceLocation Loc) { - if (TemplateDecl *Decl = AutoT->getTypeConstraintConcept()) { + if (TemplateDecl *Decl = + AutoT->getTypeConstraintConcept().getAsTemplateDecl()) { DiagnoseUseOfDecl(Decl, Loc); } } diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 3b3c9a476421d..c5250acb6541d 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -5716,7 +5716,7 @@ class ConceptInfo { // For simplicity: // - we don't attempt to substitute int for A // - when T is used in other ways (like CD<T*>) we ignore it - ConceptDecl *CD = CSE->getNamedConcept(); + ConceptDecl *CD = CSE->getConceptDecl(); TemplateParameterList *Params = CD->getTemplateParameters(); unsigned Index = 0; for (const auto &Arg : CSE->getTemplateArguments()) { @@ -5949,7 +5949,7 @@ class ConceptInfo { static QualType deduceType(const TypeConstraint &T) { // Assume a same_as<T> return type constraint is std::same_as or equivalent. // In this case the return type is T. - DeclarationName DN = T.getNamedConcept()->getDeclName(); + DeclarationName DN = T.getNamedConcept().getAsTemplateDecl()->getDeclName(); if (DN.isIdentifier() && DN.getAsIdentifierInfo()->isStr("same_as")) if (const auto *Args = T.getTemplateArgsAsWritten()) if (Args->getNumTemplateArgs() == 1) { diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index 606cfe7bdcf73..514df9c754482 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -1045,7 +1045,8 @@ ExprResult ConstraintSatisfactionChecker::EvaluateSlow( // There's a concern that even with the same concept, they may not have the // same ConceptReference, if they come from modules. if (TopLevelConceptId && - ConceptId->getNamedConcept() == TopLevelConceptId->getNamedConcept()) { + ConceptId->getNamedConcept().getAsTemplateDecl() == + TopLevelConceptId->getNamedConcept().getAsTemplateDecl()) { for (auto &A : Ori->arguments()) OutArgs.addArgument(A); } else if (S.SubstTemplateArguments(Ori->arguments(), *SubstitutedArgs, @@ -1077,7 +1078,8 @@ ExprResult ConstraintSatisfactionChecker::EvaluateSlow( ExprResult SubstitutedConceptId = S.CheckConceptTemplateId( SS, ConceptId->getTemplateKWLoc(), ConceptId->getConceptNameInfo(), - ConceptId->getFoundDecl(), ConceptId->getNamedConcept(), &OutArgs, + ConceptId->getFoundDecl(), + ConceptId->getNamedConcept().getAsTemplateDecl(), &OutArgs, /*DoCheckConstraintSatisfaction=*/false); if (SubstitutedConceptId.isInvalid() || Trap.hasErrorOccurred()) @@ -1101,7 +1103,7 @@ ExprResult ConstraintSatisfactionChecker::Evaluate( Sema::InstantiatingTemplate InstTemplate( S, ConceptId->getBeginLoc(), Sema::InstantiatingTemplate::ConstraintsCheck{}, - ConceptId->getNamedConcept(), + ConceptId->getNamedConcept().getAsTemplateDecl(), // We may have empty template arguments when checking non-dependent // nested constraint expressions. // In such cases, non-SFINAE errors would have already been diagnosed @@ -1116,7 +1118,8 @@ ExprResult ConstraintSatisfactionChecker::Evaluate( unsigned Size = Satisfaction.Details.size(); llvm::SaveAndRestore PushConceptDecl( - ParentConcept, cast<ConceptDecl>(ConceptId->getNamedConcept())); + ParentConcept, + cast<ConceptDecl>(ConceptId->getNamedConcept().getAsTemplateDecl())); ExprResult E = Evaluate(Constraint.getNormalizedConstraint(), MLTAL); @@ -1342,7 +1345,7 @@ bool Sema::CheckConstraintSatisfaction( const NamedDecl *Owner = Template; if (TopLevelConceptId) - Owner = TopLevelConceptId->getNamedConcept(); + Owner = TopLevelConceptId->getNamedConcept().getAsTemplateDecl(); llvm::FoldingSetNodeID ID; ConstraintSatisfaction::Profile(ID, Context, Owner, FlattenedArgs); @@ -1394,7 +1397,7 @@ SubstituteConceptsInConstraintExpression(Sema &S, const NamedDecl *D, // If any such substitution results in an invalid concept-id, // the program is ill-formed; no diagnostic is required. - ConceptDecl *Concept = CSE->getNamedConcept()->getCanonicalDecl(); + ConceptDecl *Concept = CSE->getConceptDecl()->getCanonicalDecl(); Sema::ArgPackSubstIndexRAII _(S, SubstIndex); const ASTTemplateArgumentListInfo *ArgsAsWritten = @@ -1915,7 +1918,7 @@ static void diagnoseUnsatisfiedConceptIdExpr(Sema &S, note_single_arg_concept_specialization_constraint_evaluated_to_false) << (int)First << Concept->getTemplateArgsAsWritten()->arguments()[0].getArgument() - << Concept->getNamedConcept(); + << Concept->getNamedConcept().getAsTemplateDecl(); } else { S.Diag(Loc, diag::note_concept_specialization_constraint_evaluated_to_false) << (int)First << Concept; @@ -2325,14 +2328,14 @@ bool SubstituteParameterMappings::substitute(ConceptIdConstraint &CC) { ArgsAsWritten->arguments(), CC.getBeginLoc(), *MLTAL, Out)) return true; Sema::CheckTemplateArgumentInfo CTAI; - if (SemaRef.CheckTemplateArgumentList(CSE->getNamedConcept(), + if (SemaRef.CheckTemplateArgumentList(CSE->getConceptDecl(), CSE->getConceptNameInfo().getLoc(), Out, /*DefaultArgs=*/{}, /*PartialTemplateArgs=*/false, CTAI, /*UpdateArgsWithConversions=*/false)) return true; auto TemplateArgs = *MLTAL; - TemplateArgs.replaceOutermostTemplateArguments(CSE->getNamedConcept(), + TemplateArgs.replaceOutermostTemplateArguments(CSE->getConceptDecl(), CTAI.SugaredConverted); return SubstituteParameterMappings(SemaRef, &TemplateArgs, ArgsAsWritten, RemovePacksForFoldExpr) @@ -2377,7 +2380,7 @@ bool SubstituteParameterMappings::substitute(NormalizedConstraint &N) { const_cast<ImplicitConceptSpecializationDecl *>( CSE->getSpecializationDecl())); SmallVector<TemplateArgument> InnerArgs(CSE->getTemplateArguments()); - ConceptDecl *Concept = CSE->getNamedConcept(); + ConceptDecl *Concept = CSE->getConceptDecl(); if (RemovePacksForFoldExpr) { TemplateArgumentListInfo OutArgs; ArrayRef<TemplateArgumentLoc> InputArgLoc = @@ -2490,7 +2493,7 @@ NormalizedConstraint *NormalizedConstraint::fromConstraintExpr( // Use canonical declarations to merge ConceptDecls across different // modules. SubNF = NormalizedConstraint::fromAssociatedConstraints( - S, CSE->getNamedConcept()->getCanonicalDecl(), + S, CSE->getConceptDecl()->getCanonicalDecl(), AssociatedConstraint(Res.get(), SubstIndex)); else return nullptr; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 1fde412749cc9..67289855685db 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -1296,12 +1296,13 @@ bool Sema::AttachTypeConstraint(NestedNameSpecifierLoc NS, if (ImmediatelyDeclaredConstraint.isInvalid()) return true; - auto *CL = ConceptReference::Create(Context, /*NNS=*/NS, - /*TemplateKWLoc=*/SourceLocation{}, - /*ConceptNameInfo=*/NameInfo, - /*FoundDecl=*/FoundDecl, - /*NamedConcept=*/NamedConcept, - /*ArgsWritten=*/ArgsAsWritten); + auto *CL = + ConceptReference::Create(Context, /*NNS=*/NS, + /*TemplateKWLoc=*/SourceLocation{}, + /*ConceptNameInfo=*/NameInfo, + /*FoundDecl=*/FoundDecl, + /*NamedConcept=*/TemplateName(NamedConcept), + /*ArgsWritten=*/ArgsAsWritten); ConstrainedParameter->setTypeConstraint( CL, ImmediatelyDeclaredConstraint.get(), std::nullopt); return false; @@ -1330,9 +1331,9 @@ bool Sema::AttachTypeConstraint(AutoTypeLoc TL, return true; ExprResult ImmediatelyDeclaredConstraint = formImmediatelyDeclaredConstraint( *this, TL.getNestedNameSpecifierLoc(), TL.getConceptNameInfo(), - TL.getNamedConcept(), /*FoundDecl=*/TL.getFoundDecl(), TL.getLAngleLoc(), - TL.getRAngleLoc(), BuildDecltypeType(Ref), - OrigConstrainedParm->getLocation(), + TL.getNamedConcept().getAsTemplateDecl(), + /*FoundDecl=*/TL.getFoundDecl(), TL.getLAngleLoc(), TL.getRAngleLoc(), + BuildDecltypeType(Ref), OrigConstrainedParm->getLocation(), [&](TemplateArgumentListInfo &ConstraintArgs) { for (unsigned I = 0, C = TL.getNumArgs(); I != C; ++I) ConstraintArgs.addArgument(TL.getArgLoc(I)); @@ -4913,7 +4914,7 @@ ExprResult Sema::CheckConceptTemplateId( auto *CL = ConceptReference::Create( Context, SS.isSet() ? SS.getWithLocInContext(Context) : NestedNameSpecifierLoc{}, - TemplateKWLoc, ConceptNameInfo, FoundDecl, NamedConcept, + TemplateKWLoc, ConceptNameInfo, FoundDecl, TemplateName(NamedConcept), ASTTemplateArgumentListInfo::Create(Context, *TemplateArgs)); bool Error = false; diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 21190031b95ea..8b9bc48bacd69 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -5350,7 +5350,8 @@ static bool CheckDeducedPlaceholderConstraints(Sema &S, const AutoType &Type, AutoTypeLoc TypeLoc, QualType Deduced) { ConstraintSatisfaction Satisfaction; - ConceptDecl *Concept = cast<ConceptDecl>(Type.getTypeConstraintConcept()); + ConceptDecl *Concept = + cast<ConceptDecl>(Type.getTypeConstraintConcept().getAsTemplateDecl()); TemplateArgumentListInfo TemplateArgs(TypeLoc.getLAngleLoc(), TypeLoc.getRAngleLoc()); TemplateArgs.addArgument( @@ -5376,9 +5377,11 @@ static bool CheckDeducedPlaceholderConstraints(Sema &S, const AutoType &Type, llvm::raw_string_ostream OS(Buf); OS << "'" << Concept->getName(); if (TypeLoc.hasExplicitTemplateArgs()) { - printTemplateArgumentList( - OS, Type.getTypeConstraintArguments(), S.getPrintingPolicy(), - Type.getTypeConstraintConcept()->getTemplateParameters()); + printTemplateArgumentList(OS, Type.getTypeConstraintArguments(), + S.getPrintingPolicy(), + Type.getTypeConstraintConcept() + .getAsTemplateDecl() + ->getTemplateParameters()); } OS << "'"; S.Diag(TypeLoc.getConceptNameLoc(), diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index f107811be868f..21781f7474e56 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -3158,7 +3158,7 @@ bool Sema::SubstTypeConstraint( } return AttachTypeConstraint( TC->getNestedNameSpecifierLoc(), TC->getConceptNameInfo(), - TC->getNamedConcept(), + TC->getNamedConcept().getAsTemplateDecl(), /*FoundDecl=*/TC->getConceptReference()->getFoundDecl(), &InstArgs, Inst, Inst->isParameterPack() ? cast<CXXFoldExpr>(TC->getImmediatelyDeclaredConstraint()) @@ -4560,8 +4560,7 @@ ExprResult Sema::SubstConceptTemplateArguments( MultiLevelTemplateArgumentList MLTALForConstraint = getTemplateInstantiationArgs( - CSE->getNamedConcept(), - CSE->getNamedConcept()->getLexicalDeclContext(), + CSE->getConceptDecl(), CSE->getConceptDecl()->getLexicalDeclContext(), /*Final=*/false, /*Innermost=*/NewArgList, /*RelativeToPrimary=*/true, diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 42ef93b98aa0a..630720c56c903 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -1344,7 +1344,8 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { } } Result = S.Context.getAutoType(DeducedKind::Undeduced, QualType(), AutoKW, - TypeConstraintConcept, TemplateArgs); + TemplateName(TypeConstraintConcept), + TemplateArgs); break; } @@ -3084,15 +3085,15 @@ InventTemplateParameter(TypeProcessingState &state, QualType T, // Create the TemplateTypeParmDecl here to retrieve the corresponding // template parameter type. Template parameters are temporarily added // to the TU until the associated TemplateDecl is created. - TemplateTypeParmDecl *InventedTemplateParam = - TemplateTypeParmDecl::Create( - S.Context, S.Context.getTranslationUnitDecl(), - /*KeyLoc=*/D.getDeclSpec().getTypeSpecTypeLoc(), - /*NameLoc=*/D.getIdentifierLoc(), - TemplateParameterDepth, AutoParameterPosition, - S.InventAbbreviatedTemplateParameterTypeName( - D.getIdentifier(), AutoParameterPosition), false, - IsParameterPack, /*HasTypeConstraint=*/Auto->isConstrained()); + TemplateTypeParmDecl *InventedTemplateParam = TemplateTypeParmDecl::Create( + S.Context, S.Context.getTranslationUnitDecl(), + /*KeyLoc=*/D.getDeclSpec().getTypeSpecTypeLoc(), + /*NameLoc=*/D.getIdentifierLoc(), TemplateParameterDepth, + AutoParameterPosition, + S.InventAbbreviatedTemplateParameterTypeName(D.getIdentifier(), + AutoParameterPosition), + false, IsParameterPack, + /*HasTypeConstraint=*/Auto->isConstrained()); InventedTemplateParam->setImplicit(); Info.TemplateParams.push_back(InventedTemplateParam); @@ -3115,7 +3116,8 @@ InventTemplateParameter(TypeProcessingState &state, QualType T, if (!Invalid) { S.AttachTypeConstraint( AutoLoc.getNestedNameSpecifierLoc(), AutoLoc.getConceptNameInfo(), - AutoLoc.getNamedConcept(), /*FoundDecl=*/AutoLoc.getFoundDecl(), + AutoLoc.getNamedConcept().getAsTemplateDecl(), + /*FoundDecl=*/AutoLoc.getFoundDecl(), AutoLoc.hasExplicitTemplateArgs() ? &TAL : nullptr, InventedTemplateParam, D.getEllipsisLoc()); } @@ -6138,9 +6140,12 @@ namespace { TemplateId->NumArgs); SemaRef.translateTemplateArguments(TemplateArgsPtr, TemplateArgsInfo); } - DeclarationNameInfo DNI = DeclarationNameInfo( - TL.getTypePtr()->getTypeConstraintConcept()->getDeclName(), - TemplateId->TemplateNameLoc); + DeclarationNameInfo DNI = + DeclarationNameInfo(TL.getTypePtr() + ->getTypeConstraintConcept() + .getAsTemplateDecl() + ->getDeclName(), + TemplateId->TemplateNameLoc); NamedDecl *FoundDecl; if (auto TN = TemplateId->Template.get(); diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index b397447ee0e52..6ce9603f633d2 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -1145,8 +1145,9 @@ class TreeTransform { AutoTypeKeyword Keyword, ConceptDecl *TypeConstraintConcept, ArrayRef<TemplateArgument> TypeConstraintArgs) { - return SemaRef.Context.getAutoType( - DK, DeducedAsType, Keyword, TypeConstraintConcept, TypeConstraintArgs); + return SemaRef.Context.getAutoType(DK, DeducedAsType, Keyword, + TemplateName(TypeConstraintConcept), + TypeConstraintArgs); } /// By default, builds a new DeducedTemplateSpecializationType with the given @@ -7568,7 +7569,8 @@ QualType TreeTransform<Derived>::TransformAutoType(TypeLocBuilder &TLB, if (T->isConstrained()) { assert(TL.getConceptReference()); NewCD = cast_or_null<ConceptDecl>(getDerived().TransformDecl( - TL.getConceptNameLoc(), T->getTypeConstraintConcept())); + TL.getConceptNameLoc(), + T->getTypeConstraintConcept().getAsTemplateDecl())); NewTemplateArgs.setLAngleLoc(TL.getLAngleLoc()); NewTemplateArgs.setRAngleLoc(TL.getRAngleLoc()); @@ -7608,10 +7610,12 @@ QualType TreeTransform<Derived>::TransformAutoType(TypeLocBuilder &TLB, NewTL.setConceptReference(nullptr); if (T->isConstrained()) { - DeclarationNameInfo DNI = DeclarationNameInfo( - TL.getTypePtr()->getTypeConstraintConcept()->getDeclName(), - TL.getConceptNameLoc(), - TL.getTypePtr()->getTypeConstraintConcept()->getDeclName()); + DeclarationName ConceptName = TL.getTypePtr() + ->getTypeConstraintConcept() + .getAsTemplateDecl() + ->getDeclName(); + DeclarationNameInfo DNI = + DeclarationNameInfo(ConceptName, TL.getConceptNameLoc(), ConceptName); auto *CR = ConceptReference::Create( SemaRef.Context, NewNestedNameSpec, TL.getTemplateKWLoc(), DNI, TL.getFoundDecl(), TL.getTypePtr()->getTypeConstraintConcept(), @@ -15629,7 +15633,7 @@ TreeTransform<Derived>::TransformConceptSpecializationExpr( return getDerived().RebuildConceptSpecializationExpr( E->getNestedNameSpecifierLoc(), E->getTemplateKWLoc(), - E->getConceptNameInfo(), E->getFoundDecl(), E->getNamedConcept(), + E->getConceptNameInfo(), E->getFoundDecl(), E->getConceptDecl(), &TransArgs); } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index c4c4b22f85093..68021fb05be16 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -7665,7 +7665,7 @@ ConceptReference *ASTRecordReader::readConceptReference() { auto TemplateKWLoc = readSourceLocation(); auto ConceptNameLoc = readDeclarationNameInfo(); auto FoundDecl = readDeclAs<NamedDecl>(); - auto NamedConcept = readDeclAs<ConceptDecl>(); + auto NamedConcept = readTemplateName(); auto *CR = ConceptReference::Create( getContext(), NNS, TemplateKWLoc, ConceptNameLoc, FoundDecl, NamedConcept, (readBool() ? readASTTemplateArgumentListInfo() : nullptr)); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 4e9af7c721d2f..5d5f3f473fd0d 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -538,7 +538,7 @@ void ASTRecordWriter::AddConceptReference(const ConceptReference *CR) { AddSourceLocation(CR->getTemplateKWLoc()); AddDeclarationNameInfo(CR->getConceptNameInfo()); AddDeclRef(CR->getFoundDecl()); - AddDeclRef(CR->getNamedConcept()); + AddTemplateName(CR->getNamedConcept()); push_back(CR->getTemplateArgsAsWritten() != nullptr); if (CR->getTemplateArgsAsWritten()) AddASTTemplateArgumentListInfo(CR->getTemplateArgsAsWritten()); diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index 47d6d2cb51efd..2c5e799d12f18 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -1344,9 +1344,8 @@ bool CursorVisitor::VisitTypeConstraint(const TypeConstraint &TC) { if (VisitNestedNameSpecifierLoc(TC.getNestedNameSpecifierLoc())) return true; } - if (TC.getNamedConcept()) { - if (Visit(MakeCursorTemplateRef(TC.getNamedConcept(), - TC.getConceptNameLoc(), TU))) + if (TemplateDecl *TD = TC.getNamedConcept().getAsTemplateDecl()) { + if (Visit(MakeCursorTemplateRef(TD, TC.getConceptNameLoc(), TU))) return true; } if (auto Args = TC.getTemplateArgsAsWritten()) { @@ -1805,9 +1804,8 @@ bool CursorVisitor::VisitAutoTypeLoc(AutoTypeLoc TL) { if (TL.isConstrained()) { if (auto *CR = TL.getConceptReference()) { - if (CR->getNamedConcept()) { - return Visit(MakeCursorTemplateRef(CR->getNamedConcept(), - CR->getConceptNameLoc(), TU)); + if (TemplateDecl *TD = CR->getNamedConcept().getAsTemplateDecl()) { + return Visit(MakeCursorTemplateRef(TD, CR->getConceptNameLoc(), TU)); } } } @@ -3993,8 +3991,8 @@ bool CursorVisitor::RunVisitorWorkList(VisitorWorkList &WL) { return true; } - if (E->getNamedConcept() && - Visit(MakeCursorTemplateRef(E->getNamedConcept(), + if (E->getNamedConcept().getAsTemplateDecl() && + Visit(MakeCursorTemplateRef(E->getConceptDecl(), E->getConceptNameLoc(), TU))) return true; >From 7e42b78d8ef352f61dd62f94a0aabad268d7eceb Mon Sep 17 00:00:00 2001 From: Corentin Jabot <[email protected]> Date: Fri, 21 Aug 2026 11:20:06 +0200 Subject: [PATCH 2/2] Assert that the TemplateName is a TemplateDecl --- clang/lib/AST/ASTConcept.cpp | 3 +++ clang/lib/AST/Type.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/clang/lib/AST/ASTConcept.cpp b/clang/lib/AST/ASTConcept.cpp index c843aa797f9ba..6a90d214de7fd 100644 --- a/clang/lib/AST/ASTConcept.cpp +++ b/clang/lib/AST/ASTConcept.cpp @@ -95,6 +95,9 @@ ConceptReference::Create(const ASTContext &C, NestedNameSpecifierLoc NNS, DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl, TemplateName NamedConcept, const ASTTemplateArgumentListInfo *ArgsAsWritten) { + + assert(NamedConcept.getKind() == TemplateName::Template); + return new (C) ConceptReference(NNS, TemplateKWLoc, ConceptNameInfo, FoundDecl, NamedConcept, ArgsAsWritten); } diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index fa346856a260c..8823843222308 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -5748,6 +5748,9 @@ AutoType::AutoType(DeducedKind DK, QualType DeducedAsTypeOrCanon, this->TypeConstraintConcept = TypeConstraintConcept; assert(!TypeConstraintConcept.isNull() || AutoTypeBits.NumArgs == 0); if (!TypeConstraintConcept.isNull()) { + + assert(TypeConstraintConcept.getKind() == TemplateName::Template); + auto Dep = toTypeDependence(TypeConstraintConcept.getDependence()); auto *ArgBuffer = _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
