-
Notifications
You must be signed in to change notification settings - Fork 14.7k
[Clang] Initial support for P2841 (Variable template and concept template parameters) #150823
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-lldb Author: Corentin Jabot (cor3ntin) ChangesThis is a first pass at implementing P2841R7. The implementation is far from complete; however, I'm aiming to do that in chunks, to make our lives easier. In particular, this does not implement
FTM, release notes, status page, etc, will be updated once the feature is more mature. Given the state of the feature, it is not yet allowed in older language modes. Of note:
Patch is 148.99 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/150823.diff 51 Files Affected:
diff --git a/clang/include/clang/AST/ASTConcept.h b/clang/include/clang/AST/ASTConcept.h
index c8f6330a73bb1..7ccac4481b14c 100644
--- a/clang/include/clang/AST/ASTConcept.h
+++ b/clang/include/clang/AST/ASTConcept.h
@@ -27,6 +27,7 @@
namespace clang {
class ConceptDecl;
+class TemplateDecl;
class Expr;
class NamedDecl;
struct PrintingPolicy;
@@ -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;
@@ -140,7 +142,7 @@ class ConceptReference {
NamedDecl *FoundDecl;
/// \brief The concept named.
- ConceptDecl *NamedConcept;
+ TemplateDecl *NamedConcept;
/// \brief The template argument list source info used to specialize the
/// concept.
@@ -148,7 +150,7 @@ class ConceptReference {
ConceptReference(NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc,
DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl,
- ConceptDecl *NamedConcept,
+ TemplateDecl *NamedConcept,
const ASTTemplateArgumentListInfo *ArgsAsWritten)
: NestedNameSpec(NNS), TemplateKWLoc(TemplateKWLoc),
ConceptName(ConceptNameInfo), FoundDecl(FoundDecl),
@@ -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 {
@@ -197,9 +199,7 @@ class ConceptReference {
return FoundDecl;
}
- ConceptDecl *getNamedConcept() const {
- return NamedConcept;
- }
+ TemplateDecl *getNamedConcept() const { return NamedConcept; }
const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
return ArgsAsWritten;
@@ -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();
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 0273109f8a698..8bdcff8b17fda 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -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;
@@ -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;
diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h
index 1ff6cc6fcb7d1..8e25f239fb97f 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -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"
@@ -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.
///
@@ -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);
@@ -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,
@@ -1746,6 +1754,16 @@ class TemplateTemplateParmDecl final
return SourceRange(getTemplateParameters()->getTemplateLoc(), End);
}
+ TemplateNameKind kind() const {
+ return static_cast<TemplateNameKind>(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; }
@@ -3341,7 +3359,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;
}
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h
index a22c32241ac61..1979aa8a97b26 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -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"
@@ -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->kind() == 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->kind() == 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())
@@ -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(); }
diff --git a/clang/include/clang/AST/ExprConcepts.h b/clang/include/clang/AST/ExprConcepts.h
index 7ab0c3e0b2769..4f162b6ffc8af 100644
--- a/clang/include/clang/AST/ExprConcepts.h
+++ b/clang/include/clang/AST/ExprConcepts.h
@@ -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.
diff --git a/clang/include/clang/AST/TemplateBase.h b/clang/include/clang/AST/TemplateBase.h
index b67036cae4261..eb384eae3faa7 100644
--- a/clang/include/clang/AST/TemplateBase.h
+++ b/clang/include/clang/AST/TemplateBase.h
@@ -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");
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 98810fbea726e..12dce309127e5 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -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:
@@ -6774,7 +6774,7 @@ class AutoType : public DeducedType {
AutoTypeBits.NumArgs};
}
- ConceptDecl *getTypeConstraintConcept() const {
+ TemplateDecl *getTypeConstraintConcept() const {
return TypeConstraintConcept;
}
@@ -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) {
diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h
index be0bc896de3ea..52ef7ac54145e 100644
--- a/clang/include/clang/AST/TypeLoc.h
+++ b/clang/include/clang/AST/TypeLoc.h
@@ -2284,7 +2284,7 @@ class AutoTypeLoc
return nullptr;
}
- ConceptDecl *getNamedConcept() const {
+ TemplateDecl *getNamedConcept() const {
if (const auto *CR = getConceptReference())
return CR->getNamedConcept();
return nullptr;
diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td
index 3114d1180319a..3373e963038f1 100644
--- a/clang/include/clang/AST/TypeProperties.td
+++ b/clang/include/clang/AST/TypeProperties.td
@@ -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() }];
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 165f01514e2b1..0042afccba2c8 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -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<
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 81cbd38d5cd24..7cfe145120ea4 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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<
@@ -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">;
diff --git a/clang/include/clang/Sema/Initialization.h b/clang/include/clang/Sema/Initialization.h
index a1c156eed5394..e5ee4b4e48ccc 100644
--- a/clang/include/clang/Sema/Initialization.h
+++ b/clang/include/clang/Sema/Initialization.h
@@ -160,7 +160,7 @@ class alignas(8) InitializedEntity {
struct VD {
/// The VarDecl, FieldDecl, or BindingDecl being initialized.
- ValueDecl *VariableOrMember;
+ NamedDecl *VariableOrMember;
/// When Kind == EK_Member, whether this is an implicit member
/// initialization in a copy or move constructor. These can perform array
@@ -291,8 +291,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;
diff --git a/clang/include/clang/Sema/Ownership.h b/clang/include/clang/Sema/Ownership.h
index 0752f5de7e334..b1520837f2f9d 100644
--- a/clang/include/clang/Sema/Ownership.h
+++ b/clang/include/clang/Sema/Ownership.h
@@ -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"
diff --git a/clang/include/clang/Sema/ParsedTemplate.h b/clang/include/clang/Sema/ParsedTemplate.h
index 3a8050f9a0a3d..6628bb88a81b9 100644
--- a/clang/include/clang/Sema/ParsedTemplate.h
+++ b/clang/include/clang/Sema/ParsedTemplate.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_SEMA_PARSEDTEMPLATE_H
#define LLVM_CLANG_SEMA_PARSEDTEMPLATE_H
+#include "clang/AST/DeclT...
[truncated]
|
@llvm/pr-subscribers-clang Author: Corentin Jabot (cor3ntin) ChangesThis is a first pass at implementing P2841R7. The implementation is far from complete; however, I'm aiming to do that in chunks, to make our lives easier. In particular, this does not implement
FTM, release notes, status page, etc, will be updated once the feature is more mature. Given the state of the feature, it is not yet allowed in older language modes. Of note:
Patch is 148.99 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/150823.diff 51 Files Affected:
diff --git a/clang/include/clang/AST/ASTConcept.h b/clang/include/clang/AST/ASTConcept.h
index c8f6330a73bb1..7ccac4481b14c 100644
--- a/clang/include/clang/AST/ASTConcept.h
+++ b/clang/include/clang/AST/ASTConcept.h
@@ -27,6 +27,7 @@
namespace clang {
class ConceptDecl;
+class TemplateDecl;
class Expr;
class NamedDecl;
struct PrintingPolicy;
@@ -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;
@@ -140,7 +142,7 @@ class ConceptReference {
NamedDecl *FoundDecl;
/// \brief The concept named.
- ConceptDecl *NamedConcept;
+ TemplateDecl *NamedConcept;
/// \brief The template argument list source info used to specialize the
/// concept.
@@ -148,7 +150,7 @@ class ConceptReference {
ConceptReference(NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc,
DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl,
- ConceptDecl *NamedConcept,
+ TemplateDecl *NamedConcept,
const ASTTemplateArgumentListInfo *ArgsAsWritten)
: NestedNameSpec(NNS), TemplateKWLoc(TemplateKWLoc),
ConceptName(ConceptNameInfo), FoundDecl(FoundDecl),
@@ -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 {
@@ -197,9 +199,7 @@ class ConceptReference {
return FoundDecl;
}
- ConceptDecl *getNamedConcept() const {
- return NamedConcept;
- }
+ TemplateDecl *getNamedConcept() const { return NamedConcept; }
const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
return ArgsAsWritten;
@@ -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();
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 0273109f8a698..8bdcff8b17fda 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -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;
@@ -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;
diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h
index 1ff6cc6fcb7d1..8e25f239fb97f 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -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"
@@ -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.
///
@@ -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);
@@ -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,
@@ -1746,6 +1754,16 @@ class TemplateTemplateParmDecl final
return SourceRange(getTemplateParameters()->getTemplateLoc(), End);
}
+ TemplateNameKind kind() const {
+ return static_cast<TemplateNameKind>(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; }
@@ -3341,7 +3359,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;
}
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h
index a22c32241ac61..1979aa8a97b26 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -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"
@@ -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->kind() == 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->kind() == 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())
@@ -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(); }
diff --git a/clang/include/clang/AST/ExprConcepts.h b/clang/include/clang/AST/ExprConcepts.h
index 7ab0c3e0b2769..4f162b6ffc8af 100644
--- a/clang/include/clang/AST/ExprConcepts.h
+++ b/clang/include/clang/AST/ExprConcepts.h
@@ -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.
diff --git a/clang/include/clang/AST/TemplateBase.h b/clang/include/clang/AST/TemplateBase.h
index b67036cae4261..eb384eae3faa7 100644
--- a/clang/include/clang/AST/TemplateBase.h
+++ b/clang/include/clang/AST/TemplateBase.h
@@ -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");
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 98810fbea726e..12dce309127e5 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -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:
@@ -6774,7 +6774,7 @@ class AutoType : public DeducedType {
AutoTypeBits.NumArgs};
}
- ConceptDecl *getTypeConstraintConcept() const {
+ TemplateDecl *getTypeConstraintConcept() const {
return TypeConstraintConcept;
}
@@ -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) {
diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h
index be0bc896de3ea..52ef7ac54145e 100644
--- a/clang/include/clang/AST/TypeLoc.h
+++ b/clang/include/clang/AST/TypeLoc.h
@@ -2284,7 +2284,7 @@ class AutoTypeLoc
return nullptr;
}
- ConceptDecl *getNamedConcept() const {
+ TemplateDecl *getNamedConcept() const {
if (const auto *CR = getConceptReference())
return CR->getNamedConcept();
return nullptr;
diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td
index 3114d1180319a..3373e963038f1 100644
--- a/clang/include/clang/AST/TypeProperties.td
+++ b/clang/include/clang/AST/TypeProperties.td
@@ -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() }];
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 165f01514e2b1..0042afccba2c8 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -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<
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 81cbd38d5cd24..7cfe145120ea4 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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<
@@ -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">;
diff --git a/clang/include/clang/Sema/Initialization.h b/clang/include/clang/Sema/Initialization.h
index a1c156eed5394..e5ee4b4e48ccc 100644
--- a/clang/include/clang/Sema/Initialization.h
+++ b/clang/include/clang/Sema/Initialization.h
@@ -160,7 +160,7 @@ class alignas(8) InitializedEntity {
struct VD {
/// The VarDecl, FieldDecl, or BindingDecl being initialized.
- ValueDecl *VariableOrMember;
+ NamedDecl *VariableOrMember;
/// When Kind == EK_Member, whether this is an implicit member
/// initialization in a copy or move constructor. These can perform array
@@ -291,8 +291,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;
diff --git a/clang/include/clang/Sema/Ownership.h b/clang/include/clang/Sema/Ownership.h
index 0752f5de7e334..b1520837f2f9d 100644
--- a/clang/include/clang/Sema/Ownership.h
+++ b/clang/include/clang/Sema/Ownership.h
@@ -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"
diff --git a/clang/include/clang/Sema/ParsedTemplate.h b/clang/include/clang/Sema/ParsedTemplate.h
index 3a8050f9a0a3d..6628bb88a81b9 100644
--- a/clang/include/clang/Sema/ParsedTemplate.h
+++ b/clang/include/clang/Sema/ParsedTemplate.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_SEMA_PARSEDTEMPLATE_H
#define LLVM_CLANG_SEMA_PARSEDTEMPLATE_H
+#include "clang/AST/DeclT...
[truncated]
|
@llvm/pr-subscribers-clang-modules Author: Corentin Jabot (cor3ntin) ChangesThis is a first pass at implementing P2841R7. The implementation is far from complete; however, I'm aiming to do that in chunks, to make our lives easier. In particular, this does not implement
FTM, release notes, status page, etc, will be updated once the feature is more mature. Given the state of the feature, it is not yet allowed in older language modes. Of note:
Patch is 148.99 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/150823.diff 51 Files Affected:
diff --git a/clang/include/clang/AST/ASTConcept.h b/clang/include/clang/AST/ASTConcept.h
index c8f6330a73bb1..7ccac4481b14c 100644
--- a/clang/include/clang/AST/ASTConcept.h
+++ b/clang/include/clang/AST/ASTConcept.h
@@ -27,6 +27,7 @@
namespace clang {
class ConceptDecl;
+class TemplateDecl;
class Expr;
class NamedDecl;
struct PrintingPolicy;
@@ -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;
@@ -140,7 +142,7 @@ class ConceptReference {
NamedDecl *FoundDecl;
/// \brief The concept named.
- ConceptDecl *NamedConcept;
+ TemplateDecl *NamedConcept;
/// \brief The template argument list source info used to specialize the
/// concept.
@@ -148,7 +150,7 @@ class ConceptReference {
ConceptReference(NestedNameSpecifierLoc NNS, SourceLocation TemplateKWLoc,
DeclarationNameInfo ConceptNameInfo, NamedDecl *FoundDecl,
- ConceptDecl *NamedConcept,
+ TemplateDecl *NamedConcept,
const ASTTemplateArgumentListInfo *ArgsAsWritten)
: NestedNameSpec(NNS), TemplateKWLoc(TemplateKWLoc),
ConceptName(ConceptNameInfo), FoundDecl(FoundDecl),
@@ -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 {
@@ -197,9 +199,7 @@ class ConceptReference {
return FoundDecl;
}
- ConceptDecl *getNamedConcept() const {
- return NamedConcept;
- }
+ TemplateDecl *getNamedConcept() const { return NamedConcept; }
const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
return ArgsAsWritten;
@@ -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();
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 0273109f8a698..8bdcff8b17fda 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -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;
@@ -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;
diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h
index 1ff6cc6fcb7d1..8e25f239fb97f 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -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"
@@ -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.
///
@@ -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);
@@ -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,
@@ -1746,6 +1754,16 @@ class TemplateTemplateParmDecl final
return SourceRange(getTemplateParameters()->getTemplateLoc(), End);
}
+ TemplateNameKind kind() const {
+ return static_cast<TemplateNameKind>(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; }
@@ -3341,7 +3359,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;
}
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h
index a22c32241ac61..1979aa8a97b26 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -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"
@@ -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->kind() == 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->kind() == 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())
@@ -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(); }
diff --git a/clang/include/clang/AST/ExprConcepts.h b/clang/include/clang/AST/ExprConcepts.h
index 7ab0c3e0b2769..4f162b6ffc8af 100644
--- a/clang/include/clang/AST/ExprConcepts.h
+++ b/clang/include/clang/AST/ExprConcepts.h
@@ -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.
diff --git a/clang/include/clang/AST/TemplateBase.h b/clang/include/clang/AST/TemplateBase.h
index b67036cae4261..eb384eae3faa7 100644
--- a/clang/include/clang/AST/TemplateBase.h
+++ b/clang/include/clang/AST/TemplateBase.h
@@ -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");
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 98810fbea726e..12dce309127e5 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -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:
@@ -6774,7 +6774,7 @@ class AutoType : public DeducedType {
AutoTypeBits.NumArgs};
}
- ConceptDecl *getTypeConstraintConcept() const {
+ TemplateDecl *getTypeConstraintConcept() const {
return TypeConstraintConcept;
}
@@ -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) {
diff --git a/clang/include/clang/AST/TypeLoc.h b/clang/include/clang/AST/TypeLoc.h
index be0bc896de3ea..52ef7ac54145e 100644
--- a/clang/include/clang/AST/TypeLoc.h
+++ b/clang/include/clang/AST/TypeLoc.h
@@ -2284,7 +2284,7 @@ class AutoTypeLoc
return nullptr;
}
- ConceptDecl *getNamedConcept() const {
+ TemplateDecl *getNamedConcept() const {
if (const auto *CR = getConceptReference())
return CR->getNamedConcept();
return nullptr;
diff --git a/clang/include/clang/AST/TypeProperties.td b/clang/include/clang/AST/TypeProperties.td
index 3114d1180319a..3373e963038f1 100644
--- a/clang/include/clang/AST/TypeProperties.td
+++ b/clang/include/clang/AST/TypeProperties.td
@@ -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() }];
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 165f01514e2b1..0042afccba2c8 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -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<
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 81cbd38d5cd24..7cfe145120ea4 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -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<
@@ -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">;
diff --git a/clang/include/clang/Sema/Initialization.h b/clang/include/clang/Sema/Initialization.h
index a1c156eed5394..e5ee4b4e48ccc 100644
--- a/clang/include/clang/Sema/Initialization.h
+++ b/clang/include/clang/Sema/Initialization.h
@@ -160,7 +160,7 @@ class alignas(8) InitializedEntity {
struct VD {
/// The VarDecl, FieldDecl, or BindingDecl being initialized.
- ValueDecl *VariableOrMember;
+ NamedDecl *VariableOrMember;
/// When Kind == EK_Member, whether this is an implicit member
/// initialization in a copy or move constructor. These can perform array
@@ -291,8 +291,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;
diff --git a/clang/include/clang/Sema/Ownership.h b/clang/include/clang/Sema/Ownership.h
index 0752f5de7e334..b1520837f2f9d 100644
--- a/clang/include/clang/Sema/Ownership.h
+++ b/clang/include/clang/Sema/Ownership.h
@@ -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"
diff --git a/clang/include/clang/Sema/ParsedTemplate.h b/clang/include/clang/Sema/ParsedTemplate.h
index 3a8050f9a0a3d..6628bb88a81b9 100644
--- a/clang/include/clang/Sema/ParsedTemplate.h
+++ b/clang/include/clang/Sema/ParsedTemplate.h
@@ -14,6 +14,7 @@
#ifndef LLVM_CLANG_SEMA_PARSEDTEMPLATE_H
#define LLVM_CLANG_SEMA_PARSEDTEMPLATE_H
+#include "clang/AST/DeclT...
[truncated]
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't quite get what is happening here yet, can you give a summary of what is being accomplished, and how you're doing so?
@@ -140,15 +142,15 @@ class ConceptReference { | |||
NamedDecl *FoundDecl; | |||
|
|||
/// \brief The concept named. | |||
ConceptDecl *NamedConcept; | |||
TemplateDecl *NamedConcept; |
There was a problem hiding this comment.
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
Let me try to see if I can enlighten you a bit. P2841 very simply extends the notion of template template parameters to variable templates and concepts (which are templates). Most of the wording complexity in P2841 deals with subsumption which is not implemented in this patch. So, what does having new kindd of template template parameters imply?
I'm happy to answer more specific questions! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few comments, else looks reasonable. Thanks for the explaination!
/// an \c Sema::TypeTy* (for a type), an Expr* (for an | ||
/// expression), or an Sema::TemplateTy (for a template). | ||
void *Arg; | ||
/// Represents the parsed form of a C++ template argument. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The diff on this file is a mess! Get I get a 'TL;DR' as to what actually changed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... nothing, apparently. I reverted the formatting changes
@@ -1746,6 +1754,16 @@ class TemplateTemplateParmDecl final | |||
return SourceRange(getTemplateParameters()->getTemplateLoc(), End); | |||
} | |||
|
|||
TemplateNameKind kind() const { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mild preference for templateKind
or something like that (perhaps something more accurate? nameKind
seems wrong toot hough)? We use kind
to mean sooooo many different things, it makes reading later not particularly descriptive.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TemplateNameKind
is pre-existing. It's the kind of a TemplateName
.
Note that I did consider using a new enum type, as we don't need all the values of TemplateNameKind, but reusing the same enums avoids having to convert back and forth.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, i wasn't suggesting changing the num name, just that kind
isn't really descriptive here. and nameKind
is a bad alternative, and templateKind
is perhaps not a great name either. So if you have a better name than kind
for the function, it would be appreciated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I somehow completely misread your point. I will think about it.
Note that core failed to come up with something better https://eel.is/c++draft/temp#param-2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on it!
I did a very cursory review and I have not dived into the details yet.
clang/lib/Sema/SemaTemplate.cpp
Outdated
UnresolvedSet<1> R; | ||
R.addDecl(CDT); | ||
ImmediatelyDeclaredConstraint = UnresolvedLookupExpr::Create( | ||
S.getASTContext(), nullptr, SS.getWithLocInContext(S.getASTContext()), | ||
SourceLocation(), NameInfo, false, &ConstraintArgs, R.begin(), R.end(), | ||
/*KnownDependent=*/false, | ||
/*KnownInstantiationDependent=*/false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we want a FIXME suggesting there's a better model than UnresolvedLookupExpr + UnresolvedSet
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added that in CheckVarOrConceptTemplateTemplateId (and moved the creation of the UnresolvedLookupExpr there)
clang/lib/Sema/SemaTemplate.cpp
Outdated
if (ImmediatelyDeclaredConstraint.isInvalid() || !EllipsisLoc.isValid()) | ||
return ImmediatelyDeclaredConstraint; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: combine & move the if 1188-1189 and 1205-1206 after the brace at line 1207
clang/lib/Sema/SemaTemplate.cpp
Outdated
ExprResult Sema::CheckVarOrConceptTemplateTemplateId( | ||
const CXXScopeSpec &, const DeclarationNameInfo &, | ||
TemplateTemplateParmDecl *Template, SourceLocation TemplateLoc, | ||
const TemplateArgumentListInfo *TemplateArgs) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't return anything other than an empty Expr or true.
Maybe bool Sema::CheckVarOrConceptTemplateTemplateId
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I modified the function to return an Expr, it removes a bit of duplication
CheckTemplateArgumentInfo CTAI; | ||
if (CheckTemplateArgumentList( | ||
Template, TemplateLoc, | ||
const_cast<TemplateArgumentListInfo &>(*TemplateArgs), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we somehow ensure the correctness of consts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not easily, I left a comment
bool Sema::CheckConceptUseInDefinition(NamedDecl *Concept, SourceLocation Loc) { | ||
if (auto *CE = llvm::dyn_cast<ConceptDecl>(Concept); | ||
CE && !CE->isInvalidDecl() && !CE->hasDefinition()) { | ||
Diag(Loc, diag::err_recursive_concept) << CE; | ||
Diag(CE->getLocation(), diag::note_declared_at); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we want a handling of TemplateTemplateParmDecl?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope, concept template parameters don't have a definition. I am adding a comment.
TemplateArgument TemplateInstantiator::TransformNamedTemplateTemplateArgument( | ||
CXXScopeSpec &SS, TemplateName Name, SourceLocation NameLoc) { | ||
if (TemplateTemplateParmDecl *TTP = | ||
dyn_cast_or_null<TemplateTemplateParmDecl>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_if_present
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather not, we are very inconsistent.
See https://discourse.llvm.org/t/psa-swapping-out-or-null-with-if-present/65018/15?u=cor3ntin
@@ -3341,7 +3359,12 @@ inline TemplateDecl *getAsTypeTemplateDecl(Decl *D) { | |||
return TD && (isa<ClassTemplateDecl>(TD) || | |||
isa<ClassTemplatePartialSpecializationDecl>(TD) || | |||
isa<TypeAliasTemplateDecl>(TD) || | |||
isa<TemplateTemplateParmDecl>(TD)) | |||
[&]() { | |||
if (TemplateTemplateParmDecl *TTP = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (TemplateTemplateParmDecl *TTP = | |
if (const auto *TTP = |
clang/lib/AST/ASTContext.cpp
Outdated
@@ -6665,7 +6668,8 @@ QualType ASTContext::getAutoTypeInternal( | |||
Canon = DeducedType.getCanonicalType(); | |||
} else if (TypeConstraintConcept) { | |||
bool AnyNonCanonArgs = false; | |||
ConceptDecl *CanonicalConcept = TypeConstraintConcept->getCanonicalDecl(); | |||
TemplateDecl *CanonicalConcept = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TemplateDecl *CanonicalConcept = | |
auto *CanonicalConcept = |
clang/lib/AST/ExprCXX.cpp
Outdated
if (std::distance(Begin, End) != 1) | ||
return false; | ||
NamedDecl *ND = *Begin; | ||
if (auto *TTP = llvm::dyn_cast<TemplateTemplateParmDecl>(ND)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (auto *TTP = llvm::dyn_cast<TemplateTemplateParmDecl>(ND)) | |
if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(ND)) |
if (parm->isParameterPack() && isa<PackExpansionType>(T)) | ||
T = cast<PackExpansionType>(T)->getPattern(); | ||
return SemaRef.SubstType(T, TemplateArgs, loc, parm->getDeclName()); | ||
if (auto NTTP = dyn_cast<NonTypeTemplateParmDecl>(parm)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (auto NTTP = dyn_cast<NonTypeTemplateParmDecl>(parm)) { | |
if (auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(parm)) { |
... right?
clang/lib/Sema/SemaTemplate.cpp
Outdated
if (TemplateTemplateParmDecl *TTP = | ||
llvm::dyn_cast<TemplateTemplateParmDecl>(TN.getAsTemplateDecl())) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (TemplateTemplateParmDecl *TTP = | |
llvm::dyn_cast<TemplateTemplateParmDecl>(TN.getAsTemplateDecl())) { | |
if (auto *TTP = | |
dyn_cast<TemplateTemplateParmDecl>(TN.getAsTemplateDecl())) { |
bool TraverseUnresolvedLookupExpr(UnresolvedLookupExpr *E) override { | ||
if (E->getNumDecls() == 1) { | ||
NamedDecl *ND = *E->decls_begin(); | ||
if (auto *TTP = llvm::dyn_cast<TemplateTemplateParmDecl>(ND); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (auto *TTP = llvm::dyn_cast<TemplateTemplateParmDecl>(ND); | |
if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(ND); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'm good with this. No real other comments here.
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/46/builds/21161 Here is the relevant piece of the build log for the reference
|
This is a first pass at implementing P2841R7.
The implementation is far from complete; however, I'm aiming to do that in chunks, to make our lives easier.
In particular, this does not implement
FTM, release notes, status page, etc, will be updated once the feature is more mature. Given the state of the feature, it is not yet allowed in older language modes.
Of note:
UnresolvedLookupExpr
to model template-id. While this is pre-existing, I have been wondering if we want to introduce a different OverloadExpr subclass for that. I did not make the change in this patch.