Skip to content
16 changes: 9 additions & 7 deletions clang/include/clang/AST/ASTConcept.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
namespace clang {

class ConceptDecl;
class TemplateDecl;
class Expr;
class NamedDecl;
struct PrintingPolicy;
Expand Down Expand Up @@ -123,6 +124,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 @@ -140,15 +142,15 @@ class ConceptReference {
NamedDecl *FoundDecl;

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

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems weird for a type named ConceptReference to not refer to a ConceptDecl anymore


/// \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 @@ -158,7 +160,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 @@ -197,9 +199,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 @@ -252,7 +252,9 @@ 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
11 changes: 6 additions & 5 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -1753,7 +1753,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 @@ -1973,10 +1973,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
46 changes: 34 additions & 12 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 @@ -1585,6 +1586,9 @@ class TemplateTemplateParmDecl final
DefaultArgStorage<TemplateTemplateParmDecl, TemplateArgumentLoc *>;
DefArgStorage DefaultArgument;

LLVM_PREFERRED_TYPE(TemplateNameKind)
unsigned ParameterKind : 3;

/// Whether this template template parameter was declaration with
/// the 'typename' keyword.
///
Expand All @@ -1607,13 +1611,16 @@ class TemplateTemplateParmDecl final

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) {}
TemplateParmPosition(D, P), ParameterKind(ParameterKind),
Typename(Typename), ParameterPack(ParameterPack),
ExpandedParameterPack(false) {}

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 @@ -1624,15 +1631,16 @@ 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,
TemplateParameterList *Params,
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);

static TemplateTemplateParmDecl *CreateDeserialized(ASTContext &C,
Expand Down Expand Up @@ -1746,6 +1754,16 @@ class TemplateTemplateParmDecl final
return SourceRange(getTemplateParameters()->getTemplateLoc(), End);
}

TemplateNameKind templateParameterKind() const {
return static_cast<TemplateNameKind>(ParameterKind);
}

bool isTypeConceptTemplateParam() const {
return templateParameterKind() == 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; }
Expand Down Expand Up @@ -3341,7 +3359,11 @@ inline TemplateDecl *getAsTypeTemplateDecl(Decl *D) {
return TD && (isa<ClassTemplateDecl>(TD) ||
isa<ClassTemplatePartialSpecializationDecl>(TD) ||
isa<TypeAliasTemplateDecl>(TD) ||
isa<TemplateTemplateParmDecl>(TD))
[&]() {
if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TD))
return TTP->templateParameterKind() == TNK_Type_template;
return false;
}())
? TD
: nullptr;
}
Expand Down
47 changes: 45 additions & 2 deletions clang/include/clang/AST/ExprCXX.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/TemplateKinds.h"
#include "clang/Basic/TypeTraits.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/PointerUnion.h"
Expand Down Expand Up @@ -3257,7 +3258,49 @@ class OverloadExpr : public Expr {
bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); }

/// Determines whether this expression had explicit template arguments.
bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); }
bool hasExplicitTemplateArgs() const {
if (!hasTemplateKWAndArgsInfo())
return false;
// FIXME: deduced function types can have "hidden" args and no <
// investigate that further, but ultimately maybe we want to model concepts
// reference with another kind of expression.
return (isConceptReference() || isVarDeclReference())
? getTrailingASTTemplateKWAndArgsInfo()->NumTemplateArgs
: getLAngleLoc().isValid();
}

bool isConceptReference() const {
return getNumDecls() == 1 && [&]() {
if (auto *TTP = dyn_cast_or_null<TemplateTemplateParmDecl>(
getTrailingResults()->getDecl()))
return TTP->templateParameterKind() == TNK_Concept_template;
if (isa<ConceptDecl>(getTrailingResults()->getDecl()))
return true;
return false;
}();
}

bool isVarDeclReference() const {
return getNumDecls() == 1 && [&]() {
if (auto *TTP = dyn_cast_or_null<TemplateTemplateParmDecl>(
getTrailingResults()->getDecl()))
return TTP->templateParameterKind() == TNK_Var_template;
if (isa<VarTemplateDecl>(getTrailingResults()->getDecl()))
return true;
return false;
}();
}

TemplateDecl *getTemplateDecl() const {
assert(getNumDecls() == 1);
return dyn_cast_or_null<TemplateDecl>(getTrailingResults()->getDecl());
}

TemplateTemplateParmDecl *getTemplateTemplateDecl() const {
assert(getNumDecls() == 1);
return dyn_cast_or_null<TemplateTemplateParmDecl>(
getTrailingResults()->getDecl());
}

TemplateArgumentLoc const *getTemplateArgs() const {
if (!hasExplicitTemplateArgs())
Expand Down Expand Up @@ -4658,7 +4701,7 @@ class SubstNonTypeTemplateParmExpr : public Expr {
// sugared: it doesn't need to be resugared later.
bool getFinal() const { return Final; }

NonTypeTemplateParmDecl *getParameter() const;
NamedDecl *getParameter() const;

bool isReferenceParameter() const { return AssociatedDeclAndRef.getInt(); }

Expand Down
4 changes: 3 additions & 1 deletion clang/include/clang/AST/ExprConcepts.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ class ConceptSpecializationExpr final : public Expr {

ConceptReference *getConceptReference() const { return ConceptRef; }

ConceptDecl *getNamedConcept() const { return ConceptRef->getNamedConcept(); }
ConceptDecl *getNamedConcept() const {
return cast<ConceptDecl>(ConceptRef->getNamedConcept());
}

// FIXME: Several of the following functions can be removed. Instead the
// caller can directly work with the ConceptReference.
Expand Down
2 changes: 2 additions & 0 deletions clang/include/clang/AST/TemplateBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,8 @@ class TemplateArgument {
/// Determine whether this template argument is a pack expansion.
bool isPackExpansion() const;

bool isConceptOrConceptTemplateParameter() const;

/// Retrieve the type for a type template argument.
QualType getAsType() const {
assert(getKind() == Type && "Unexpected kind");
Expand Down
8 changes: 4 additions & 4 deletions clang/include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -6762,10 +6762,10 @@ class DeducedType : public Type {
class AutoType : public DeducedType {
friend class ASTContext; // ASTContext creates these

ConceptDecl *TypeConstraintConcept;
TemplateDecl *TypeConstraintConcept;

AutoType(QualType DeducedAsType, AutoTypeKeyword Keyword,
TypeDependence ExtraDependence, QualType Canon, ConceptDecl *CD,
TypeDependence ExtraDependence, QualType Canon, TemplateDecl *CD,
ArrayRef<TemplateArgument> TypeConstraintArgs);

public:
Expand All @@ -6774,7 +6774,7 @@ class AutoType : public DeducedType {
AutoTypeBits.NumArgs};
}

ConceptDecl *getTypeConstraintConcept() const {
TemplateDecl *getTypeConstraintConcept() const {
return TypeConstraintConcept;
}

Expand All @@ -6797,7 +6797,7 @@ class AutoType : public DeducedType {
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context);
static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
QualType Deduced, AutoTypeKeyword Keyword,
bool IsDependent, ConceptDecl *CD,
bool IsDependent, TemplateDecl *CD,
ArrayRef<TemplateArgument> Arguments);

static bool classof(const Type *T) {
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/AST/TypeLoc.h
Original file line number Diff line number Diff line change
Expand Up @@ -2284,7 +2284,7 @@ class AutoTypeLoc
return nullptr;
}

ConceptDecl *getNamedConcept() const {
TemplateDecl *getNamedConcept() const {
if (const auto *CR = getConceptReference())
return CR->getNamedConcept();
return nullptr;
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/AST/TypeProperties.td
Original file line number Diff line number Diff line change
Expand Up @@ -495,9 +495,9 @@ let Class = AutoType in {
def : Property<"keyword", AutoTypeKeyword> {
let Read = [{ node->getKeyword() }];
}
def : Property<"typeConstraintConcept", Optional<ConceptDeclRef>> {
def : Property<"typeConstraintConcept", Optional<TemplateDeclRef>> {
let Read = [{ makeOptionalFromPointer(
const_cast<const ConceptDecl*>(node->getTypeConstraintConcept())) }];
node->getTypeConstraintConcept()) }];
}
def : Property<"typeConstraintArguments", Array<TemplateArgument>> {
let Read = [{ node->getTypeConstraintArguments() }];
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/Basic/DiagnosticParseKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -931,6 +931,10 @@ def err_missing_dependent_template_keyword : Error<
def warn_missing_dependent_template_keyword : ExtWarn<
"use 'template' keyword to treat '%0' as a dependent template name">;

def err_cxx26_template_template_params
: Error<"%select{variable template|concept}0 template parameter is a C++2c "
"extension">;

def ext_extern_template : Extension<
"extern templates are a C++11 extension">, InGroup<CXX11>;
def warn_cxx98_compat_extern_template : Warning<
Expand Down
19 changes: 12 additions & 7 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -5441,8 +5441,10 @@ def err_template_arg_must_be_expr : Error<
"template argument for non-type template parameter must be an expression">;
def err_template_arg_nontype_ambig : Error<
"template argument for non-type template parameter is treated as function type %0">;
def err_template_arg_must_be_template : Error<
"template argument for template template parameter must be a class template%select{| or type alias template}0">;
def err_template_arg_must_be_template
: Error<"template argument for template template parameter must be a "
"%select{class template%select{| or type alias template}1|variable "
"template|concept}0">;
def ext_template_arg_local_type : ExtWarn<
"template argument uses local type %0">, InGroup<LocalTypeTemplateArgs>;
def ext_template_arg_unnamed_type : ExtWarn<
Expand All @@ -5457,11 +5459,14 @@ def note_template_unnamed_type_here : Note<
"unnamed type used in template argument was declared here">;
def err_template_arg_overload_type : Error<
"template argument is the type of an unresolved overloaded function">;
def err_template_arg_not_valid_template : Error<
"template argument does not refer to a class or alias template, or template "
"template parameter">;
def note_template_arg_refers_here_func : Note<
"template argument refers to function template %0, here">;
def err_template_arg_not_valid_template
: Error<"template argument does not refer to a %select{class or alias "
"template|variable template|concept}0, or template "
"template parameter">;

def note_template_arg_refers_to_template_here
: Note<"template argument refers to a %select{function template|class "
"template|variable template|concept}0 %1, here">;
def err_template_arg_template_params_mismatch : Error<
"template template argument has different template parameters than its "
"corresponding template template parameter">;
Expand Down
9 changes: 5 additions & 4 deletions clang/include/clang/Sema/Initialization.h
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,9 @@ class alignas(8) InitializedEntity {
};

struct VD {
/// The VarDecl, FieldDecl, or BindingDecl being initialized.
ValueDecl *VariableOrMember;
/// The VarDecl, FieldDecl, TemplateParmDecl, or BindingDecl being
/// initialized.
NamedDecl *VariableOrMember;

/// When Kind == EK_Member, whether this is an implicit member
/// initialization in a copy or move constructor. These can perform array
Expand Down Expand Up @@ -291,8 +292,8 @@ class alignas(8) InitializedEntity {
}

/// Create the initialization entity for a template parameter.
static InitializedEntity
InitializeTemplateParameter(QualType T, NonTypeTemplateParmDecl *Param) {
static InitializedEntity InitializeTemplateParameter(QualType T,
NamedDecl *Param) {
InitializedEntity Entity;
Entity.Kind = EK_TemplateParameter;
Entity.Type = T;
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Sema/Ownership.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#ifndef LLVM_CLANG_SEMA_OWNERSHIP_H
#define LLVM_CLANG_SEMA_OWNERSHIP_H

#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
Expand Down
Loading
Loading