Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
7d217e5
non type template template parameters (wip)
cor3ntin Mar 18, 2023
da8c879
[Clang] Improve diagnostics when using a concept as template argument
cor3ntin Mar 23, 2023
6c6dc6a
Concept template parameter subsumption
cor3ntin Mar 27, 2023
e4696c5
[Clang] Support concept template parameters as type constraints
cor3ntin Apr 10, 2023
6080337
Use a templatedecl instead of a namedecl
cor3ntin Apr 10, 2023
c147f9d
fix tests
cor3ntin Apr 10, 2023
ff342ef
Work around the fact that UnresolvedLookupExpr can have args
cor3ntin Apr 10, 2023
49b7088
Support default arguments for template template parameters
cor3ntin Apr 11, 2023
cf25ce2
Partially applied concepts (wip)
cor3ntin Apr 14, 2023
f925457
Fix dependence of TTP parameter
cor3ntin Apr 18, 2023
73e756f
Fix concept param arity matching + add test file
cor3ntin Apr 18, 2023
256d3f7
Fix subsumption for concept template parameters
cor3ntin Apr 23, 2023
895fb72
subsumption for partial concepts
cor3ntin Apr 25, 2023
af717cb
Fix build
cor3ntin May 13, 2023
411e8e5
Fix build
cor3ntin May 13, 2023
3cb9722
Fix crash when using an unexisting concvept as partial concept
cor3ntin May 14, 2023
54a7261
Fix build after rebase
cor3ntin Sep 17, 2023
063daf7
[WIP] Universal template parameters
cor3ntin Sep 19, 2023
c0f5fb1
Fix rebase
cor3ntin Oct 22, 2023
bd1e6e1
Fix mangling crash
cor3ntin Oct 23, 2023
74146aa
First pass at argument deduction for non type template parameter
cor3ntin Oct 24, 2023
c8ae96b
Use a symbolic reference model for id-expression NTTP arguments
cor3ntin Dec 13, 2023
1893c4b
Subsumption for fold expressions not involving concept template param…
cor3ntin Nov 26, 2023
b645cc5
Dependent concept-id during partial ordering should result in a subst…
cor3ntin Feb 20, 2024
99cd439
Fix rebase
cor3ntin Apr 11, 2024
58cedbb
Merge remote-tracking branch 'llvm_be_very_careful/main' into corenti…
cor3ntin Sep 30, 2024
b93e741
fix merge
cor3ntin Sep 30, 2024
d658277
Temporarily revert partially applied concepts to simplify the diff
cor3ntin Oct 4, 2024
7fb869e
Reintroduce partially applied concepts
cor3ntin May 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 57 additions & 7 deletions clang/include/clang/AST/ASTConcept.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
namespace clang {

class ConceptDecl;
class TemplateDecl;
class Expr;
class NamedDecl;
struct PrintingPolicy;
Expand Down Expand Up @@ -122,6 +123,7 @@ struct ASTConstraintSatisfaction final :
/// template <std::derives_from<Expr> T> void dump();
/// ~~~~~~~~~~~~~~~~~~~~~~~ (in TemplateTypeParmDecl)
class ConceptReference {
protected:
// \brief The optional nested name specifier used when naming the concept.
NestedNameSpecifierLoc NestedNameSpec;

Expand All @@ -139,15 +141,15 @@ class ConceptReference {
NamedDecl *FoundDecl;

/// \brief The concept named.
ConceptDecl *NamedConcept;
TemplateDecl *NamedConcept;

/// \brief The template argument list source info used to specialize the
/// concept.
const ASTTemplateArgumentListInfo *ArgsAsWritten;

ConceptReference(NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc,
DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl,
ConceptDecl *NamedConcept,
TemplateDecl *NamedConcept,
const ASTTemplateArgumentListInfo *ArgsAsWritten)
: NestedNameSpec(NNS), TemplateKWLoc(TemplateKWLoc),
ConceptName(ConceptNameInfo), FoundDecl(FoundDecl),
Expand All @@ -157,7 +159,7 @@ class ConceptReference {
static ConceptReference *
Create(const ASTContext &C, NestedNameSpecifierLoc NNS,
SourceLocation TemplateKWLoc, DeclarationNameInfo ConceptNameInfo,
NamedDecl *FoundDecl, ConceptDecl *NamedConcept,
NamedDecl *FoundDecl, TemplateDecl *NamedConcept,
const ASTTemplateArgumentListInfo *ArgsAsWritten);

const NestedNameSpecifierLoc &getNestedNameSpecifierLoc() const {
Expand Down Expand Up @@ -196,9 +198,7 @@ class ConceptReference {
return FoundDecl;
}

ConceptDecl *getNamedConcept() const {
return NamedConcept;
}
TemplateDecl *getNamedConcept() const { return NamedConcept; }

const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
return ArgsAsWritten;
Expand Down Expand Up @@ -247,7 +247,7 @@ class TypeConstraint {

// FIXME: Instead of using these concept related functions the callers should
// directly work with the corresponding ConceptReference.
ConceptDecl *getNamedConcept() const { return ConceptRef->getNamedConcept(); }
TemplateDecl *getNamedConcept() const { return ConceptRef->getNamedConcept(); }

SourceLocation getConceptNameLoc() const {
return ConceptRef->getConceptNameLoc();
Expand Down Expand Up @@ -278,6 +278,56 @@ class TypeConstraint {
void print(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const {
ConceptRef->print(OS, Policy);
}

};

class PartiallyAppliedConcept : public ConceptReference,
public llvm::FoldingSetNode {

SourceLocation ConceptKWLoc;
PartiallyAppliedConcept(NestedNameSpecifierLoc NNS,
DeclarationNameInfo ConceptNameInfo,
SourceLocation ConceptKWLoc, NamedDecl *FoundDecl,
TemplateDecl *NamedConcept,
const ASTTemplateArgumentListInfo *ArgsAsWritten)
: ConceptReference(NNS, /*TemplateKWLoc=*/SourceLocation(),
ConceptNameInfo, FoundDecl, NamedConcept,
ArgsAsWritten),
ConceptKWLoc(ConceptKWLoc) {}

public:
static PartiallyAppliedConcept *
Create(const ASTContext &C, NestedNameSpecifierLoc NNS,
DeclarationNameInfo ConceptNameInfo, SourceLocation ConceptKWLoc,
NamedDecl *FoundDecl, TemplateDecl *NamedConcept,
const TemplateArgumentListInfo &TemplateArgs);

TemplateArgumentDependence getDependence() const;

bool isDependent() const {
return getDependence() & TemplateArgumentDependence::Dependent;
}

bool isInstantiationDependent() const {
return getDependence() & TemplateArgumentDependence::Instantiation;
}

void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C) const {
Profile(ID, C, getNamedConcept(), getTemplateArgsAsWritten());
}

static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &C,
const TemplateDecl *NamedConcept,
const ASTTemplateArgumentListInfo *ArgsAsWritten);

SourceLocation getConceptKWLoc() const { return ConceptKWLoc; }

SourceRange getSourceRange() const {
return {ConceptKWLoc, ArgsAsWritten->getRAngleLoc()};
}

friend const StreamingDiagnostic &operator<<(const StreamingDiagnostic &DB,
PartiallyAppliedConcept &C);
};

} // clang
Expand Down
17 changes: 12 additions & 5 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "clang/AST/PrettyPrinter.h"
#include "clang/AST/RawCommentList.h"
#include "clang/AST/TemplateName.h"
#include "clang/AST/UniversalTemplateParameterName.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/SourceLocation.h"
Expand Down Expand Up @@ -96,6 +97,7 @@ class ObjCTypeParamDecl;
class OMPTraitInfo;
class ParentMapContext;
struct ParsedTargetAttr;
class PartiallyAppliedConcept;
class Preprocessor;
class ProfileList;
class StoredDeclsMap;
Expand Down Expand Up @@ -1660,7 +1662,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
QualType
getAutoTypeInternal(QualType DeducedType, AutoTypeKeyword Keyword,
bool IsDependent, bool IsPack = false,
ConceptDecl *TypeConstraintConcept = nullptr,
TemplateDecl *TypeConstraintConcept = nullptr,
ArrayRef<TemplateArgument> TypeConstraintArgs = {},
bool IsCanon = false) const;

Expand Down Expand Up @@ -1825,10 +1827,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
UnaryTransformType::UTTKind UKind) const;

/// C++11 deduced auto type.
QualType getAutoType(QualType DeducedType, AutoTypeKeyword Keyword,
bool IsDependent, bool IsPack = false,
ConceptDecl *TypeConstraintConcept = nullptr,
ArrayRef<TemplateArgument> TypeConstraintArgs ={}) const;
QualType
getAutoType(QualType DeducedType, AutoTypeKeyword Keyword, bool IsDependent,
bool IsPack = false,
TemplateDecl *TypeConstraintConcept = nullptr,
ArrayRef<TemplateArgument> TypeConstraintArgs = {}) const;

/// C++11 deduction pattern for 'auto' type.
QualType getAutoDeductType() const;
Expand Down Expand Up @@ -2334,6 +2337,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
unsigned Index,
bool Final) const;

UniversalTemplateParameterName *
getUniversalTemplateParameterName(SourceLocation Loc,
DeclarationNameInfo Name,
UniversalTemplateParmDecl *Decl) const;
/// Represents a TemplateName which had some of its default arguments
/// deduced. This both represents this default argument deduction as sugar,
/// and provides the support for it's equivalences through canonicalization.
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/AST/ASTNodeTraverser.h
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,8 @@ class ASTNodeTraverser
D->defaultArgumentWasInherited() ? "inherited from" : "previous");
}

void VisitUniversalTemplateParmDecl(const UniversalTemplateParmDecl *D) {}

void VisitConceptDecl(const ConceptDecl *D) {
dumpTemplateParameters(D->getTemplateParameters());
Visit(D->getConstraintExpr());
Expand Down
120 changes: 109 additions & 11 deletions clang/include/clang/AST/DeclTemplate.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TemplateKinds.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/PointerIntPair.h"
Expand Down Expand Up @@ -53,6 +54,7 @@ class IdentifierInfo;
class NonTypeTemplateParmDecl;
class TemplateDecl;
class TemplateTemplateParmDecl;
class UniversalTemplateParmDecl;
class TemplateTypeParmDecl;
class ConceptDecl;
class UnresolvedSetImpl;
Expand All @@ -62,7 +64,7 @@ class VarTemplatePartialSpecializationDecl;
/// Stores a template parameter of any kind.
using TemplateParameter =
llvm::PointerUnion<TemplateTypeParmDecl *, NonTypeTemplateParmDecl *,
TemplateTemplateParmDecl *>;
TemplateTemplateParmDecl *, UniversalTemplateParmDecl *>;

NamedDecl *getAsNamedDecl(TemplateParameter P);

Expand Down Expand Up @@ -1600,15 +1602,22 @@ class TemplateTemplateParmDecl final
/// The number of parameters in an expanded parameter pack.
unsigned NumExpandedParams = 0;

TemplateNameKind ParameterKind = TemplateNameKind::TNK_Type_template;

TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
unsigned P, bool ParameterPack, IdentifierInfo *Id,
bool Typename, TemplateParameterList *Params)
TemplateNameKind ParameterKind,
bool Typename,
TemplateParameterList *Params)
: TemplateDecl(TemplateTemplateParm, DC, L, Id, Params),
TemplateParmPosition(D, P), Typename(Typename),
ParameterPack(ParameterPack), ExpandedParameterPack(false) {}
ParameterPack(ParameterPack),
ExpandedParameterPack(false), ParameterKind(ParameterKind) {}

TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
unsigned P, IdentifierInfo *Id, bool Typename,
unsigned P, IdentifierInfo *Id,
TemplateNameKind ParameterKind,
bool Typename,
TemplateParameterList *Params,
ArrayRef<TemplateParameterList *> Expansions);

Expand All @@ -1619,14 +1628,17 @@ class TemplateTemplateParmDecl final
friend class ASTDeclWriter;
friend TrailingObjects;

static TemplateTemplateParmDecl *Create(const ASTContext &C, DeclContext *DC,
SourceLocation L, unsigned D,
unsigned P, bool ParameterPack,
IdentifierInfo *Id, bool Typename,
TemplateParameterList *Params);
static TemplateTemplateParmDecl *
Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D,
unsigned P, IdentifierInfo *Id, bool Typename,
unsigned P, bool ParameterPack, IdentifierInfo *Id,
TemplateNameKind ParameterKind, bool Typename,
TemplateParameterList *Params);

static TemplateTemplateParmDecl *
Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D,
unsigned P, IdentifierInfo *Id,
TemplateNameKind ParameterKind,
bool Typename,
TemplateParameterList *Params,
ArrayRef<TemplateParameterList *> Expansions);

Expand Down Expand Up @@ -1741,11 +1753,90 @@ class TemplateTemplateParmDecl final
return SourceRange(getTemplateParameters()->getTemplateLoc(), End);
}

TemplateNameKind kind() const {
return ParameterKind;
}

bool isTypeConceptTemplateParam() const {
return kind() == TemplateNameKind::TNK_Concept_template &&
getTemplateParameters()->size() > 0 &&
isa<TemplateTypeParmDecl>(getTemplateParameters()->getParam(0));
}

// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == TemplateTemplateParm; }
};

class UniversalTemplateParmDecl final : public NamedDecl,
protected TemplateParmPosition {

/// Whether this universal template parameter is a parameter pack.
bool ParameterPack;

UniversalTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
unsigned P, bool ParameterPack, IdentifierInfo *Id)
: NamedDecl(UniversalTemplateParm, DC, L, Id), TemplateParmPosition(D, P),
ParameterPack(ParameterPack) {}

// UniversalTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D,
// unsigned P, IdentifierInfo *Id,
// TemplateNameKind ParameterKind,
// TemplateParameterList *Params,
// ArrayRef<TemplateParameterList *> Expansions);

void anchor() override {}

public:
friend class ASTDeclReader;
friend class ASTDeclWriter;

static UniversalTemplateParmDecl *Create(const ASTContext &C, DeclContext *DC,
SourceLocation L, unsigned D,
unsigned P, bool ParameterPack,
IdentifierInfo *Id);

// static TemplateTemplateParmDecl *
// Create(const ASTContext &C, DeclContext *DC, SourceLocation L, unsigned D,
/// unsigned P, IdentifierInfo *Id, TemplateNameKind ParameterKind,
// TemplateParameterList *Params,
// ArrayRef<TemplateParameterList *> Expansions);

static TemplateTemplateParmDecl *CreateDeserialized(ASTContext &C,
unsigned ID);
// static TemplateTemplateParmDecl *CreateDeserialized(ASTContext &C,
// unsigned ID,
// unsigned
// NumExpansions);

using TemplateParmPosition::getDepth;
using TemplateParmPosition::getIndex;
using TemplateParmPosition::getPosition;
using TemplateParmPosition::setDepth;
using TemplateParmPosition::setPosition;

/// Whether this template template parameter is a template
/// parameter pack.
///
/// \code
/// template<template <class T> ...MetaFunctions> struct Apply;
/// \endcode
bool isParameterPack() const { return ParameterPack; }

// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == UniversalTemplateParm; }

void Profile(llvm::FoldingSetNodeID &ID) const {
Profile(ID, ParameterPack, getASTContext());
}

static void Profile(llvm::FoldingSetNodeID &ID, bool ParameterPack,
const ASTContext &Context) {
ID.AddBoolean(ParameterPack);
}
};

/// Represents the builtin template declaration which is used to
/// implement __make_integer_seq and other builtin templates. It serves
/// no real purpose beyond existing as a place to hold template parameters.
Expand Down Expand Up @@ -3296,6 +3387,8 @@ inline NamedDecl *getAsNamedDecl(TemplateParameter P) {
return PD;
if (auto *PD = P.dyn_cast<NonTypeTemplateParmDecl *>())
return PD;
if (auto *PD = P.dyn_cast<UniversalTemplateParmDecl *>())
return PD;
return P.get<TemplateTemplateParmDecl *>();
}

Expand All @@ -3304,7 +3397,12 @@ inline TemplateDecl *getAsTypeTemplateDecl(Decl *D) {
return TD && (isa<ClassTemplateDecl>(TD) ||
isa<ClassTemplatePartialSpecializationDecl>(TD) ||
isa<TypeAliasTemplateDecl>(TD) ||
isa<TemplateTemplateParmDecl>(TD))
[&]() {
if (TemplateTemplateParmDecl *TTP =
dyn_cast<TemplateTemplateParmDecl>(TD))
return TTP->kind() == TNK_Type_template;
return false;
}())
? TD
: nullptr;
}
Expand Down
Loading