[Concept] Associated Constraints Infrastructure
Add code to correctly calculate the associated constraints of a template (no enforcement yet). D41284 on Phabricator. llvm-svn: 374938
This commit is contained in:
parent
5836c356fa
commit
0330fba6e1
|
|
@ -237,6 +237,9 @@ public:
|
||||||
|
|
||||||
for (const auto &TP : *TPL)
|
for (const auto &TP : *TPL)
|
||||||
Visit(TP);
|
Visit(TP);
|
||||||
|
|
||||||
|
if (const Expr *RC = TPL->getRequiresClause())
|
||||||
|
Visit(RC);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -168,6 +168,16 @@ public:
|
||||||
return HasRequiresClause ? *getTrailingObjects<Expr *>() : nullptr;
|
return HasRequiresClause ? *getTrailingObjects<Expr *>() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief All associated constraints derived from this template parameter
|
||||||
|
/// list, including the requires clause and any constraints derived from
|
||||||
|
/// constrained-parameters.
|
||||||
|
///
|
||||||
|
/// The constraints in the resulting list are to be treated as if in a
|
||||||
|
/// conjunction ("and").
|
||||||
|
void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const;
|
||||||
|
|
||||||
|
bool hasAssociatedConstraints() const;
|
||||||
|
|
||||||
SourceLocation getTemplateLoc() const { return TemplateLoc; }
|
SourceLocation getTemplateLoc() const { return TemplateLoc; }
|
||||||
SourceLocation getLAngleLoc() const { return LAngleLoc; }
|
SourceLocation getLAngleLoc() const { return LAngleLoc; }
|
||||||
SourceLocation getRAngleLoc() const { return RAngleLoc; }
|
SourceLocation getRAngleLoc() const { return RAngleLoc; }
|
||||||
|
|
@ -369,33 +379,7 @@ public:
|
||||||
// Kinds of Templates
|
// Kinds of Templates
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
/// Stores the template parameter list and associated constraints for
|
/// \brief The base class of all kinds of template declarations (e.g.,
|
||||||
/// \c TemplateDecl objects that track associated constraints.
|
|
||||||
class ConstrainedTemplateDeclInfo {
|
|
||||||
friend TemplateDecl;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ConstrainedTemplateDeclInfo() = default;
|
|
||||||
|
|
||||||
TemplateParameterList *getTemplateParameters() const {
|
|
||||||
return TemplateParams;
|
|
||||||
}
|
|
||||||
|
|
||||||
Expr *getAssociatedConstraints() const { return AssociatedConstraints; }
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void setTemplateParameters(TemplateParameterList *TParams) {
|
|
||||||
TemplateParams = TParams;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setAssociatedConstraints(Expr *AC) { AssociatedConstraints = AC; }
|
|
||||||
|
|
||||||
TemplateParameterList *TemplateParams = nullptr;
|
|
||||||
Expr *AssociatedConstraints = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/// The base class of all kinds of template declarations (e.g.,
|
|
||||||
/// class, function, etc.).
|
/// class, function, etc.).
|
||||||
///
|
///
|
||||||
/// The TemplateDecl class stores the list of template parameters and a
|
/// The TemplateDecl class stores the list of template parameters and a
|
||||||
|
|
@ -404,54 +388,32 @@ class TemplateDecl : public NamedDecl {
|
||||||
void anchor() override;
|
void anchor() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
// Construct a template decl with name, parameters, and templated element.
|
||||||
|
TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name,
|
||||||
|
TemplateParameterList *Params, NamedDecl *Decl);
|
||||||
|
|
||||||
// Construct a template decl with the given name and parameters.
|
// Construct a template decl with the given name and parameters.
|
||||||
// Used when there is no templated element (e.g., for tt-params).
|
// Used when there is no templated element (e.g., for tt-params).
|
||||||
TemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK, DeclContext *DC,
|
|
||||||
SourceLocation L, DeclarationName Name,
|
|
||||||
TemplateParameterList *Params)
|
|
||||||
: NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr),
|
|
||||||
TemplateParams(CTDI) {
|
|
||||||
this->setTemplateParameters(Params);
|
|
||||||
}
|
|
||||||
|
|
||||||
TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name,
|
TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name,
|
||||||
TemplateParameterList *Params)
|
TemplateParameterList *Params)
|
||||||
: TemplateDecl(nullptr, DK, DC, L, Name, Params) {}
|
: TemplateDecl(DK, DC, L, Name, Params, nullptr) {}
|
||||||
|
|
||||||
// Construct a template decl with name, parameters, and templated element.
|
|
||||||
TemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK, DeclContext *DC,
|
|
||||||
SourceLocation L, DeclarationName Name,
|
|
||||||
TemplateParameterList *Params, NamedDecl *Decl)
|
|
||||||
: NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl),
|
|
||||||
TemplateParams(CTDI) {
|
|
||||||
this->setTemplateParameters(Params);
|
|
||||||
}
|
|
||||||
|
|
||||||
TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name,
|
|
||||||
TemplateParameterList *Params, NamedDecl *Decl)
|
|
||||||
: TemplateDecl(nullptr, DK, DC, L, Name, Params, Decl) {}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
friend class ASTDeclReader;
|
||||||
|
friend class ASTDeclWriter;
|
||||||
|
|
||||||
/// Get the list of template parameters
|
/// Get the list of template parameters
|
||||||
TemplateParameterList *getTemplateParameters() const {
|
TemplateParameterList *getTemplateParameters() const {
|
||||||
const auto *const CTDI =
|
return TemplateParams;
|
||||||
TemplateParams.dyn_cast<ConstrainedTemplateDeclInfo *>();
|
|
||||||
return CTDI ? CTDI->getTemplateParameters()
|
|
||||||
: TemplateParams.get<TemplateParameterList *>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the constraint-expression from the associated requires-clause (if any)
|
/// \brief Get the total constraint-expression associated with this template,
|
||||||
const Expr *getRequiresClause() const {
|
/// including constraint-expressions derived from the requires-clause,
|
||||||
const TemplateParameterList *const TP = getTemplateParameters();
|
/// trailing requires-clause (for functions and methods) and constrained
|
||||||
return TP ? TP->getRequiresClause() : nullptr;
|
/// template parameters.
|
||||||
}
|
void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const;
|
||||||
|
|
||||||
Expr *getAssociatedConstraints() const {
|
bool hasAssociatedConstraints() const;
|
||||||
const auto *const C = cast<TemplateDecl>(getCanonicalDecl());
|
|
||||||
const auto *const CTDI =
|
|
||||||
C->TemplateParams.dyn_cast<ConstrainedTemplateDeclInfo *>();
|
|
||||||
return CTDI ? CTDI->getAssociatedConstraints() : nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the underlying, templated declaration.
|
/// Get the underlying, templated declaration.
|
||||||
NamedDecl *getTemplatedDecl() const { return TemplatedDecl; }
|
NamedDecl *getTemplatedDecl() const { return TemplatedDecl; }
|
||||||
|
|
@ -470,30 +432,11 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
NamedDecl *TemplatedDecl;
|
NamedDecl *TemplatedDecl;
|
||||||
|
TemplateParameterList *TemplateParams;
|
||||||
/// The template parameter list and optional requires-clause
|
|
||||||
/// associated with this declaration; alternatively, a
|
|
||||||
/// \c ConstrainedTemplateDeclInfo if the associated constraints of the
|
|
||||||
/// template are being tracked by this particular declaration.
|
|
||||||
llvm::PointerUnion<TemplateParameterList *,
|
|
||||||
ConstrainedTemplateDeclInfo *>
|
|
||||||
TemplateParams;
|
|
||||||
|
|
||||||
void setTemplateParameters(TemplateParameterList *TParams) {
|
void setTemplateParameters(TemplateParameterList *TParams) {
|
||||||
if (auto *const CTDI =
|
|
||||||
TemplateParams.dyn_cast<ConstrainedTemplateDeclInfo *>()) {
|
|
||||||
CTDI->setTemplateParameters(TParams);
|
|
||||||
} else {
|
|
||||||
TemplateParams = TParams;
|
TemplateParams = TParams;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void setAssociatedConstraints(Expr *AC) {
|
|
||||||
assert(isCanonicalDecl() &&
|
|
||||||
"Attaching associated constraints to non-canonical Decl");
|
|
||||||
TemplateParams.get<ConstrainedTemplateDeclInfo *>()
|
|
||||||
->setAssociatedConstraints(AC);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// Initialize the underlying templated declaration and
|
/// Initialize the underlying templated declaration and
|
||||||
|
|
@ -889,17 +832,10 @@ protected:
|
||||||
virtual CommonBase *newCommon(ASTContext &C) const = 0;
|
virtual CommonBase *newCommon(ASTContext &C) const = 0;
|
||||||
|
|
||||||
// Construct a template decl with name, parameters, and templated element.
|
// Construct a template decl with name, parameters, and templated element.
|
||||||
RedeclarableTemplateDecl(ConstrainedTemplateDeclInfo *CTDI, Kind DK,
|
|
||||||
ASTContext &C, DeclContext *DC, SourceLocation L,
|
|
||||||
DeclarationName Name, TemplateParameterList *Params,
|
|
||||||
NamedDecl *Decl)
|
|
||||||
: TemplateDecl(CTDI, DK, DC, L, Name, Params, Decl), redeclarable_base(C)
|
|
||||||
{}
|
|
||||||
|
|
||||||
RedeclarableTemplateDecl(Kind DK, ASTContext &C, DeclContext *DC,
|
RedeclarableTemplateDecl(Kind DK, ASTContext &C, DeclContext *DC,
|
||||||
SourceLocation L, DeclarationName Name,
|
SourceLocation L, DeclarationName Name,
|
||||||
TemplateParameterList *Params, NamedDecl *Decl)
|
TemplateParameterList *Params, NamedDecl *Decl)
|
||||||
: RedeclarableTemplateDecl(nullptr, DK, C, DC, L, Name, Params, Decl) {}
|
: TemplateDecl(DK, DC, L, Name, Params, Decl), redeclarable_base(C) {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
friend class ASTDeclReader;
|
friend class ASTDeclReader;
|
||||||
|
|
@ -2026,6 +1962,20 @@ public:
|
||||||
return TemplateParams;
|
return TemplateParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \brief All associated constraints of this partial specialization,
|
||||||
|
/// including the requires clause and any constraints derived from
|
||||||
|
/// constrained-parameters.
|
||||||
|
///
|
||||||
|
/// The constraints in the resulting list are to be treated as if in a
|
||||||
|
/// conjunction ("and").
|
||||||
|
void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const {
|
||||||
|
TemplateParams->getAssociatedConstraints(AC);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasAssociatedConstraints() const {
|
||||||
|
return TemplateParams->hasAssociatedConstraints();
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the template arguments as written.
|
/// Get the template arguments as written.
|
||||||
const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
|
const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
|
||||||
return ArgsAsWritten;
|
return ArgsAsWritten;
|
||||||
|
|
@ -2145,16 +2095,10 @@ protected:
|
||||||
llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &
|
llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &
|
||||||
getPartialSpecializations();
|
getPartialSpecializations();
|
||||||
|
|
||||||
ClassTemplateDecl(ConstrainedTemplateDeclInfo *CTDI, ASTContext &C,
|
|
||||||
DeclContext *DC, SourceLocation L, DeclarationName Name,
|
|
||||||
TemplateParameterList *Params, NamedDecl *Decl)
|
|
||||||
: RedeclarableTemplateDecl(CTDI, ClassTemplate, C, DC, L, Name, Params,
|
|
||||||
Decl) {}
|
|
||||||
|
|
||||||
ClassTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L,
|
ClassTemplateDecl(ASTContext &C, DeclContext *DC, SourceLocation L,
|
||||||
DeclarationName Name, TemplateParameterList *Params,
|
DeclarationName Name, TemplateParameterList *Params,
|
||||||
NamedDecl *Decl)
|
NamedDecl *Decl)
|
||||||
: ClassTemplateDecl(nullptr, C, DC, L, Name, Params, Decl) {}
|
: RedeclarableTemplateDecl(ClassTemplate, C, DC, L, Name, Params, Decl) {}
|
||||||
|
|
||||||
CommonBase *newCommon(ASTContext &C) const override;
|
CommonBase *newCommon(ASTContext &C) const override;
|
||||||
|
|
||||||
|
|
@ -2180,14 +2124,12 @@ public:
|
||||||
return getTemplatedDecl()->isThisDeclarationADefinition();
|
return getTemplatedDecl()->isThisDeclarationADefinition();
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: remove default argument for AssociatedConstraints
|
/// \brief Create a class template node.
|
||||||
/// Create a class template node.
|
|
||||||
static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC,
|
static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC,
|
||||||
SourceLocation L,
|
SourceLocation L,
|
||||||
DeclarationName Name,
|
DeclarationName Name,
|
||||||
TemplateParameterList *Params,
|
TemplateParameterList *Params,
|
||||||
NamedDecl *Decl,
|
NamedDecl *Decl);
|
||||||
Expr *AssociatedConstraints = nullptr);
|
|
||||||
|
|
||||||
/// Create an empty class template node.
|
/// Create an empty class template node.
|
||||||
static ClassTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
static ClassTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
|
||||||
|
|
@ -2862,7 +2804,21 @@ public:
|
||||||
return ArgsAsWritten;
|
return ArgsAsWritten;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve the member variable template partial specialization from
|
/// \brief All associated constraints of this partial specialization,
|
||||||
|
/// including the requires clause and any constraints derived from
|
||||||
|
/// constrained-parameters.
|
||||||
|
///
|
||||||
|
/// The constraints in the resulting list are to be treated as if in a
|
||||||
|
/// conjunction ("and").
|
||||||
|
void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const {
|
||||||
|
TemplateParams->getAssociatedConstraints(AC);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasAssociatedConstraints() const {
|
||||||
|
return TemplateParams->hasAssociatedConstraints();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Retrieve the member variable template partial specialization from
|
||||||
/// which this particular variable template partial specialization was
|
/// which this particular variable template partial specialization was
|
||||||
/// instantiated.
|
/// instantiated.
|
||||||
///
|
///
|
||||||
|
|
@ -3091,11 +3047,9 @@ class ConceptDecl : public TemplateDecl, public Mergeable<ConceptDecl> {
|
||||||
protected:
|
protected:
|
||||||
Expr *ConstraintExpr;
|
Expr *ConstraintExpr;
|
||||||
|
|
||||||
ConceptDecl(DeclContext *DC,
|
ConceptDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
|
||||||
SourceLocation L, DeclarationName Name,
|
TemplateParameterList *Params, Expr *ConstraintExpr)
|
||||||
TemplateParameterList *Params,
|
: TemplateDecl(Concept, DC, L, Name, Params),
|
||||||
Expr *ConstraintExpr)
|
|
||||||
: TemplateDecl(nullptr, Concept, DC, L, Name, Params),
|
|
||||||
ConstraintExpr(ConstraintExpr) {};
|
ConstraintExpr(ConstraintExpr) {};
|
||||||
public:
|
public:
|
||||||
static ConceptDecl *Create(ASTContext &C, DeclContext *DC,
|
static ConceptDecl *Create(ASTContext &C, DeclContext *DC,
|
||||||
|
|
|
||||||
|
|
@ -1633,9 +1633,11 @@ template <typename Derived>
|
||||||
bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper(
|
bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper(
|
||||||
TemplateParameterList *TPL) {
|
TemplateParameterList *TPL) {
|
||||||
if (TPL) {
|
if (TPL) {
|
||||||
for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end();
|
for (NamedDecl *D : *TPL) {
|
||||||
I != E; ++I) {
|
TRY_TO(TraverseDecl(D));
|
||||||
TRY_TO(TraverseDecl(*I));
|
}
|
||||||
|
if (Expr *RequiresClause = TPL->getRequiresClause()) {
|
||||||
|
TRY_TO(TraverseStmt(RequiresClause));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
||||||
|
|
@ -2543,8 +2543,8 @@ def err_non_constant_constraint_expression : Error<
|
||||||
def err_non_bool_atomic_constraint : Error<
|
def err_non_bool_atomic_constraint : Error<
|
||||||
"atomic constraint must be of type 'bool' (found %0)">;
|
"atomic constraint must be of type 'bool' (found %0)">;
|
||||||
|
|
||||||
def err_template_different_associated_constraints : Error<
|
def err_template_different_requires_clause : Error<
|
||||||
"associated constraints differ in template redeclaration">;
|
"requires clause differs in template redeclaration">;
|
||||||
|
|
||||||
// C++11 char16_t/char32_t
|
// C++11 char16_t/char32_t
|
||||||
def warn_cxx98_compat_unicode_type : Warning<
|
def warn_cxx98_compat_unicode_type : Warning<
|
||||||
|
|
|
||||||
|
|
@ -6058,6 +6058,12 @@ public:
|
||||||
Expr *ConstraintExpr,
|
Expr *ConstraintExpr,
|
||||||
bool &IsSatisfied);
|
bool &IsSatisfied);
|
||||||
|
|
||||||
|
/// Check that the associated constraints of a template declaration match the
|
||||||
|
/// associated constraints of an older declaration of which it is a
|
||||||
|
/// redeclaration.
|
||||||
|
bool CheckRedeclarationConstraintMatch(TemplateParameterList *Old,
|
||||||
|
TemplateParameterList *New);
|
||||||
|
|
||||||
// ParseObjCStringLiteral - Parse Objective-C string literals.
|
// ParseObjCStringLiteral - Parse Objective-C string literals.
|
||||||
ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
|
ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
|
||||||
ArrayRef<Expr *> Strings);
|
ArrayRef<Expr *> Strings);
|
||||||
|
|
|
||||||
|
|
@ -738,7 +738,7 @@ ASTContext::getCanonicalTemplateTemplateParmDecl(
|
||||||
cast<TemplateTemplateParmDecl>(*P)));
|
cast<TemplateTemplateParmDecl>(*P)));
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(!TTP->getRequiresClause() &&
|
assert(!TTP->getTemplateParameters()->getRequiresClause() &&
|
||||||
"Unexpected requires-clause on template template-parameter");
|
"Unexpected requires-clause on template template-parameter");
|
||||||
Expr *const CanonRequiresClause = nullptr;
|
Expr *const CanonRequiresClause = nullptr;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,8 @@ TemplateParameterList::TemplateParameterList(SourceLocation TemplateLoc,
|
||||||
}
|
}
|
||||||
if (RequiresClause) {
|
if (RequiresClause) {
|
||||||
*getTrailingObjects<Expr *>() = RequiresClause;
|
*getTrailingObjects<Expr *>() = RequiresClause;
|
||||||
|
if (RequiresClause->containsUnexpandedParameterPack())
|
||||||
|
ContainsUnexpandedParameterPack = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -136,6 +138,18 @@ static void AdoptTemplateParameterList(TemplateParameterList *Params,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TemplateParameterList::
|
||||||
|
getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const {
|
||||||
|
// TODO: Concepts: Collect immediately-introduced constraints.
|
||||||
|
if (HasRequiresClause)
|
||||||
|
AC.push_back(getRequiresClause());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TemplateParameterList::hasAssociatedConstraints() const {
|
||||||
|
// TODO: Concepts: Regard immediately-introduced constraints.
|
||||||
|
return HasRequiresClause;
|
||||||
|
}
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
|
|
||||||
void *allocateDefaultArgStorageChain(const ASTContext &C) {
|
void *allocateDefaultArgStorageChain(const ASTContext &C) {
|
||||||
|
|
@ -144,6 +158,28 @@ void *allocateDefaultArgStorageChain(const ASTContext &C) {
|
||||||
|
|
||||||
} // namespace clang
|
} // namespace clang
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// TemplateDecl Implementation
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
TemplateDecl::TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
|
||||||
|
DeclarationName Name, TemplateParameterList *Params,
|
||||||
|
NamedDecl *Decl)
|
||||||
|
: NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl), TemplateParams(Params) {}
|
||||||
|
|
||||||
|
void TemplateDecl::anchor() {}
|
||||||
|
|
||||||
|
void TemplateDecl::
|
||||||
|
getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const {
|
||||||
|
// TODO: Concepts: Append function trailing requires clause.
|
||||||
|
TemplateParams->getAssociatedConstraints(AC);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TemplateDecl::hasAssociatedConstraints() const {
|
||||||
|
// TODO: Concepts: Regard function trailing requires clause.
|
||||||
|
return TemplateParams->hasAssociatedConstraints();
|
||||||
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// RedeclarableTemplateDecl Implementation
|
// RedeclarableTemplateDecl Implementation
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
@ -344,19 +380,10 @@ ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C,
|
||||||
SourceLocation L,
|
SourceLocation L,
|
||||||
DeclarationName Name,
|
DeclarationName Name,
|
||||||
TemplateParameterList *Params,
|
TemplateParameterList *Params,
|
||||||
NamedDecl *Decl,
|
NamedDecl *Decl) {
|
||||||
Expr *AssociatedConstraints) {
|
|
||||||
AdoptTemplateParameterList(Params, cast<DeclContext>(Decl));
|
AdoptTemplateParameterList(Params, cast<DeclContext>(Decl));
|
||||||
|
|
||||||
if (!AssociatedConstraints) {
|
|
||||||
return new (C, DC) ClassTemplateDecl(C, DC, L, Name, Params, Decl);
|
return new (C, DC) ClassTemplateDecl(C, DC, L, Name, Params, Decl);
|
||||||
}
|
|
||||||
|
|
||||||
auto *const CTDI = new (C) ConstrainedTemplateDeclInfo;
|
|
||||||
auto *const New =
|
|
||||||
new (C, DC) ClassTemplateDecl(CTDI, C, DC, L, Name, Params, Decl);
|
|
||||||
New->setAssociatedConstraints(AssociatedConstraints);
|
|
||||||
return New;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C,
|
ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C,
|
||||||
|
|
@ -707,12 +734,6 @@ FunctionTemplateSpecializationInfo *FunctionTemplateSpecializationInfo::Create(
|
||||||
FD, Template, TSK, TemplateArgs, ArgsAsWritten, POI, MSInfo);
|
FD, Template, TSK, TemplateArgs, ArgsAsWritten, POI, MSInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// TemplateDecl Implementation
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
void TemplateDecl::anchor() {}
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// ClassTemplateSpecializationDecl Implementation
|
// ClassTemplateSpecializationDecl Implementation
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
|
||||||
|
|
@ -45,27 +45,7 @@ clang::getTemplateParamsRange(TemplateParameterList const * const *Ps,
|
||||||
return SourceRange(Ps[0]->getTemplateLoc(), Ps[N-1]->getRAngleLoc());
|
return SourceRange(Ps[0]->getTemplateLoc(), Ps[N-1]->getRAngleLoc());
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace clang {
|
/// \brief Determine whether the declaration found is acceptable as the name
|
||||||
/// [temp.constr.decl]p2: A template's associated constraints are
|
|
||||||
/// defined as a single constraint-expression derived from the introduced
|
|
||||||
/// constraint-expressions [ ... ].
|
|
||||||
///
|
|
||||||
/// \param Params The template parameter list and optional requires-clause.
|
|
||||||
///
|
|
||||||
/// \param FD The underlying templated function declaration for a function
|
|
||||||
/// template.
|
|
||||||
static Expr *formAssociatedConstraints(TemplateParameterList *Params,
|
|
||||||
FunctionDecl *FD);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Expr *clang::formAssociatedConstraints(TemplateParameterList *Params,
|
|
||||||
FunctionDecl *FD) {
|
|
||||||
// FIXME: Concepts: collect additional introduced constraint-expressions
|
|
||||||
assert(!FD && "Cannot collect constraints from function declaration yet.");
|
|
||||||
return Params->getRequiresClause();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Determine whether the declaration found is acceptable as the name
|
|
||||||
/// of a template and, if so, return that template declaration. Otherwise,
|
/// of a template and, if so, return that template declaration. Otherwise,
|
||||||
/// returns null.
|
/// returns null.
|
||||||
///
|
///
|
||||||
|
|
@ -1533,9 +1513,6 @@ DeclResult Sema::CheckClassTemplate(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Memory management; associated constraints are not always stored.
|
|
||||||
Expr *const CurAC = formAssociatedConstraints(TemplateParams, nullptr);
|
|
||||||
|
|
||||||
if (PrevClassTemplate) {
|
if (PrevClassTemplate) {
|
||||||
// Ensure that the template parameter lists are compatible. Skip this check
|
// Ensure that the template parameter lists are compatible. Skip this check
|
||||||
// for a friend in a dependent context: the template parameter list itself
|
// for a friend in a dependent context: the template parameter list itself
|
||||||
|
|
@ -1547,30 +1524,6 @@ DeclResult Sema::CheckClassTemplate(
|
||||||
TPL_TemplateMatch))
|
TPL_TemplateMatch))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Check for matching associated constraints on redeclarations.
|
|
||||||
const Expr *const PrevAC = PrevClassTemplate->getAssociatedConstraints();
|
|
||||||
const bool RedeclACMismatch = [&] {
|
|
||||||
if (!(CurAC || PrevAC))
|
|
||||||
return false; // Nothing to check; no mismatch.
|
|
||||||
if (CurAC && PrevAC) {
|
|
||||||
llvm::FoldingSetNodeID CurACInfo, PrevACInfo;
|
|
||||||
CurAC->Profile(CurACInfo, Context, /*Canonical=*/true);
|
|
||||||
PrevAC->Profile(PrevACInfo, Context, /*Canonical=*/true);
|
|
||||||
if (CurACInfo == PrevACInfo)
|
|
||||||
return false; // All good; no mismatch.
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}();
|
|
||||||
|
|
||||||
if (RedeclACMismatch) {
|
|
||||||
Diag(CurAC ? CurAC->getBeginLoc() : NameLoc,
|
|
||||||
diag::err_template_different_associated_constraints);
|
|
||||||
Diag(PrevAC ? PrevAC->getBeginLoc() : PrevClassTemplate->getLocation(),
|
|
||||||
diag::note_template_prev_declaration)
|
|
||||||
<< /*declaration*/ 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// C++ [temp.class]p4:
|
// C++ [temp.class]p4:
|
||||||
// In a redeclaration, partial specialization, explicit
|
// In a redeclaration, partial specialization, explicit
|
||||||
// specialization or explicit instantiation of a class template,
|
// specialization or explicit instantiation of a class template,
|
||||||
|
|
@ -1674,15 +1627,10 @@ DeclResult Sema::CheckClassTemplate(
|
||||||
AddMsStructLayoutForRecord(NewClass);
|
AddMsStructLayoutForRecord(NewClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Attach the associated constraints when the declaration will not be part of
|
|
||||||
// a decl chain.
|
|
||||||
Expr *const ACtoAttach =
|
|
||||||
PrevClassTemplate && ShouldAddRedecl ? nullptr : CurAC;
|
|
||||||
|
|
||||||
ClassTemplateDecl *NewTemplate
|
ClassTemplateDecl *NewTemplate
|
||||||
= ClassTemplateDecl::Create(Context, SemanticContext, NameLoc,
|
= ClassTemplateDecl::Create(Context, SemanticContext, NameLoc,
|
||||||
DeclarationName(Name), TemplateParams,
|
DeclarationName(Name), TemplateParams,
|
||||||
NewClass, ACtoAttach);
|
NewClass);
|
||||||
|
|
||||||
if (ShouldAddRedecl)
|
if (ShouldAddRedecl)
|
||||||
NewTemplate->setPreviousDecl(PrevClassTemplate);
|
NewTemplate->setPreviousDecl(PrevClassTemplate);
|
||||||
|
|
@ -7266,6 +7214,9 @@ static bool MatchTemplateParameterKind(Sema &S, NamedDecl *New, NamedDecl *Old,
|
||||||
TemplateArgLoc);
|
TemplateArgLoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Concepts: Match immediately-introduced-constraint for type
|
||||||
|
// constraints
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -7291,6 +7242,15 @@ void DiagnoseTemplateParameterListArityMismatch(Sema &S,
|
||||||
<< SourceRange(Old->getTemplateLoc(), Old->getRAngleLoc());
|
<< SourceRange(Old->getTemplateLoc(), Old->getRAngleLoc());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
DiagnoseTemplateParameterListRequiresClauseMismatch(Sema &S,
|
||||||
|
TemplateParameterList *New,
|
||||||
|
TemplateParameterList *Old){
|
||||||
|
S.Diag(New->getTemplateLoc(), diag::err_template_different_requires_clause);
|
||||||
|
S.Diag(Old->getTemplateLoc(), diag::note_template_prev_declaration)
|
||||||
|
<< /*declaration*/0;
|
||||||
|
}
|
||||||
|
|
||||||
/// Determine whether the given template parameter lists are
|
/// Determine whether the given template parameter lists are
|
||||||
/// equivalent.
|
/// equivalent.
|
||||||
///
|
///
|
||||||
|
|
@ -7380,6 +7340,27 @@ Sema::TemplateParameterListsAreEqual(TemplateParameterList *New,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Kind != TPL_TemplateTemplateArgumentMatch) {
|
||||||
|
const Expr *NewRC = New->getRequiresClause();
|
||||||
|
const Expr *OldRC = Old->getRequiresClause();
|
||||||
|
if (!NewRC != !OldRC) {
|
||||||
|
if (Complain)
|
||||||
|
DiagnoseTemplateParameterListRequiresClauseMismatch(*this, New, Old);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NewRC) {
|
||||||
|
llvm::FoldingSetNodeID OldRCID, NewRCID;
|
||||||
|
OldRC->Profile(OldRCID, Context, /*Canonical=*/true);
|
||||||
|
NewRC->Profile(NewRCID, Context, /*Canonical=*/true);
|
||||||
|
if (OldRCID != NewRCID) {
|
||||||
|
if (Complain)
|
||||||
|
DiagnoseTemplateParameterListRequiresClauseMismatch(*this, New, Old);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -8089,10 +8070,9 @@ Decl *Sema::ActOnConceptDefinition(Scope *S,
|
||||||
TemplateParameterLists.front(),
|
TemplateParameterLists.front(),
|
||||||
ConstraintExpr);
|
ConstraintExpr);
|
||||||
|
|
||||||
if (NewDecl->getAssociatedConstraints()) {
|
if (NewDecl->hasAssociatedConstraints()) {
|
||||||
// C++2a [temp.concept]p4:
|
// C++2a [temp.concept]p4:
|
||||||
// A concept shall not have associated constraints.
|
// A concept shall not have associated constraints.
|
||||||
// TODO: Make a test once we have actual associated constraints.
|
|
||||||
Diag(NameLoc, diag::err_concept_no_associated_constraints);
|
Diag(NameLoc, diag::err_concept_no_associated_constraints);
|
||||||
NewDecl->setInvalidDecl();
|
NewDecl->setInvalidDecl();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3515,14 +3515,21 @@ TemplateDeclInstantiator::SubstTemplateParams(TemplateParameterList *L) {
|
||||||
if (Invalid)
|
if (Invalid)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
// Note: we substitute into associated constraints later
|
// FIXME: Concepts: Substitution into requires clause should only happen when
|
||||||
Expr *const UninstantiatedRequiresClause = L->getRequiresClause();
|
// checking satisfaction.
|
||||||
|
Expr *InstRequiresClause = nullptr;
|
||||||
|
if (Expr *E = L->getRequiresClause()) {
|
||||||
|
ExprResult Res = SemaRef.SubstExpr(E, TemplateArgs);
|
||||||
|
if (Res.isInvalid() || !Res.isUsable()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
InstRequiresClause = Res.get();
|
||||||
|
}
|
||||||
|
|
||||||
TemplateParameterList *InstL
|
TemplateParameterList *InstL
|
||||||
= TemplateParameterList::Create(SemaRef.Context, L->getTemplateLoc(),
|
= TemplateParameterList::Create(SemaRef.Context, L->getTemplateLoc(),
|
||||||
L->getLAngleLoc(), Params,
|
L->getLAngleLoc(), Params,
|
||||||
L->getRAngleLoc(),
|
L->getRAngleLoc(), InstRequiresClause);
|
||||||
UninstantiatedRequiresClause);
|
|
||||||
return InstL;
|
return InstL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9345,9 +9345,11 @@ ASTReader::ReadTemplateParameterList(ModuleFile &F,
|
||||||
while (NumParams--)
|
while (NumParams--)
|
||||||
Params.push_back(ReadDeclAs<NamedDecl>(F, Record, Idx));
|
Params.push_back(ReadDeclAs<NamedDecl>(F, Record, Idx));
|
||||||
|
|
||||||
// TODO: Concepts
|
bool HasRequiresClause = Record[Idx++];
|
||||||
|
Expr *RequiresClause = HasRequiresClause ? ReadExpr(F) : nullptr;
|
||||||
|
|
||||||
TemplateParameterList *TemplateParams = TemplateParameterList::Create(
|
TemplateParameterList *TemplateParams = TemplateParameterList::Create(
|
||||||
getContext(), TemplateLoc, LAngleLoc, Params, RAngleLoc, nullptr);
|
getContext(), TemplateLoc, LAngleLoc, Params, RAngleLoc, RequiresClause);
|
||||||
return TemplateParams;
|
return TemplateParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2000,7 +2000,6 @@ DeclID ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) {
|
||||||
DeclID PatternID = ReadDeclID();
|
DeclID PatternID = ReadDeclID();
|
||||||
auto *TemplatedDecl = cast_or_null<NamedDecl>(Reader.GetDecl(PatternID));
|
auto *TemplatedDecl = cast_or_null<NamedDecl>(Reader.GetDecl(PatternID));
|
||||||
TemplateParameterList *TemplateParams = Record.readTemplateParameterList();
|
TemplateParameterList *TemplateParams = Record.readTemplateParameterList();
|
||||||
// FIXME handle associated constraints
|
|
||||||
D->init(TemplatedDecl, TemplateParams);
|
D->init(TemplatedDecl, TemplateParams);
|
||||||
|
|
||||||
return PatternID;
|
return PatternID;
|
||||||
|
|
@ -2166,7 +2165,8 @@ void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl(
|
||||||
ClassTemplatePartialSpecializationDecl *D) {
|
ClassTemplatePartialSpecializationDecl *D) {
|
||||||
RedeclarableResult Redecl = VisitClassTemplateSpecializationDeclImpl(D);
|
RedeclarableResult Redecl = VisitClassTemplateSpecializationDeclImpl(D);
|
||||||
|
|
||||||
D->TemplateParams = Record.readTemplateParameterList();
|
TemplateParameterList *Params = Record.readTemplateParameterList();
|
||||||
|
D->TemplateParams = Params;
|
||||||
D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo();
|
D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo();
|
||||||
|
|
||||||
// These are read/set from/to the first declaration.
|
// These are read/set from/to the first declaration.
|
||||||
|
|
@ -2268,7 +2268,8 @@ void ASTDeclReader::VisitVarTemplatePartialSpecializationDecl(
|
||||||
VarTemplatePartialSpecializationDecl *D) {
|
VarTemplatePartialSpecializationDecl *D) {
|
||||||
RedeclarableResult Redecl = VisitVarTemplateSpecializationDeclImpl(D);
|
RedeclarableResult Redecl = VisitVarTemplateSpecializationDeclImpl(D);
|
||||||
|
|
||||||
D->TemplateParams = Record.readTemplateParameterList();
|
TemplateParameterList *Params = Record.readTemplateParameterList();
|
||||||
|
D->TemplateParams = Params;
|
||||||
D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo();
|
D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo();
|
||||||
|
|
||||||
// These are read/set from/to the first declaration.
|
// These are read/set from/to the first declaration.
|
||||||
|
|
@ -2284,6 +2285,7 @@ void ASTDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
|
||||||
|
|
||||||
D->setDeclaredWithTypename(Record.readInt());
|
D->setDeclaredWithTypename(Record.readInt());
|
||||||
|
|
||||||
|
// TODO: Concepts: Immediately introduced constraint
|
||||||
if (Record.readInt())
|
if (Record.readInt())
|
||||||
D->setDefaultArgument(GetTypeSourceInfo());
|
D->setDefaultArgument(GetTypeSourceInfo());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6070,10 +6070,16 @@ void ASTRecordWriter::AddTemplateParameterList(
|
||||||
AddSourceLocation(TemplateParams->getTemplateLoc());
|
AddSourceLocation(TemplateParams->getTemplateLoc());
|
||||||
AddSourceLocation(TemplateParams->getLAngleLoc());
|
AddSourceLocation(TemplateParams->getLAngleLoc());
|
||||||
AddSourceLocation(TemplateParams->getRAngleLoc());
|
AddSourceLocation(TemplateParams->getRAngleLoc());
|
||||||
// TODO: Concepts
|
|
||||||
Record->push_back(TemplateParams->size());
|
Record->push_back(TemplateParams->size());
|
||||||
for (const auto &P : *TemplateParams)
|
for (const auto &P : *TemplateParams)
|
||||||
AddDeclRef(P);
|
AddDeclRef(P);
|
||||||
|
if (const Expr *RequiresClause = TemplateParams->getRequiresClause()) {
|
||||||
|
Record->push_back(true);
|
||||||
|
AddStmt(const_cast<Expr*>(RequiresClause));
|
||||||
|
} else {
|
||||||
|
Record->push_back(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Emit a template argument list.
|
/// Emit a template argument list.
|
||||||
|
|
|
||||||
|
|
@ -1608,7 +1608,7 @@ void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
|
||||||
VisitTypeDecl(D);
|
VisitTypeDecl(D);
|
||||||
|
|
||||||
Record.push_back(D->wasDeclaredWithTypename());
|
Record.push_back(D->wasDeclaredWithTypename());
|
||||||
|
// TODO: Concepts - constrained parameters.
|
||||||
bool OwnsDefaultArg = D->hasDefaultArgument() &&
|
bool OwnsDefaultArg = D->hasDefaultArgument() &&
|
||||||
!D->defaultArgumentWasInherited();
|
!D->defaultArgumentWasInherited();
|
||||||
Record.push_back(OwnsDefaultArg);
|
Record.push_back(OwnsDefaultArg);
|
||||||
|
|
@ -1638,6 +1638,7 @@ void ASTDeclWriter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
|
||||||
|
|
||||||
Code = serialization::DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK;
|
Code = serialization::DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK;
|
||||||
} else {
|
} else {
|
||||||
|
// TODO: Concepts - constrained parameters.
|
||||||
// Rest of NonTypeTemplateParmDecl.
|
// Rest of NonTypeTemplateParmDecl.
|
||||||
Record.push_back(D->isParameterPack());
|
Record.push_back(D->isParameterPack());
|
||||||
bool OwnsDefaultArg = D->hasDefaultArgument() &&
|
bool OwnsDefaultArg = D->hasDefaultArgument() &&
|
||||||
|
|
@ -1667,6 +1668,7 @@ void ASTDeclWriter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
|
||||||
Record.AddTemplateParameterList(D->getExpansionTemplateParameters(I));
|
Record.AddTemplateParameterList(D->getExpansionTemplateParameters(I));
|
||||||
Code = serialization::DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK;
|
Code = serialization::DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK;
|
||||||
} else {
|
} else {
|
||||||
|
// TODO: Concepts - constrained parameters.
|
||||||
// Rest of TemplateTemplateParmDecl.
|
// Rest of TemplateTemplateParmDecl.
|
||||||
Record.push_back(D->isParameterPack());
|
Record.push_back(D->isParameterPack());
|
||||||
bool OwnsDefaultArg = D->hasDefaultArgument() &&
|
bool OwnsDefaultArg = D->hasDefaultArgument() &&
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
// RUN: %clang_cc1 -std=c++2a -verify %s
|
||||||
|
|
||||||
|
template<typename T> requires true
|
||||||
|
concept C = true; // expected-error{{concept cannot have associated constraints}}
|
||||||
|
|
||||||
|
// TODO: Add test for other kinds of associated constraints once we have them.
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// RUN: %clang_cc1 -std=c++14 -fconcepts-ts -x c++ -verify %s
|
// RUN: %clang_cc1 -std=c++2a -x c++ -verify %s
|
||||||
|
|
||||||
namespace nodiag {
|
namespace nodiag {
|
||||||
|
|
||||||
|
|
@ -13,15 +13,15 @@ namespace diag {
|
||||||
|
|
||||||
template <typename T> requires true // expected-note{{previous template declaration is here}}
|
template <typename T> requires true // expected-note{{previous template declaration is here}}
|
||||||
struct A;
|
struct A;
|
||||||
template <typename T> struct A; // expected-error{{associated constraints differ in template redeclaration}}
|
template <typename T> struct A; // expected-error{{requires clause differs in template redeclaration}}
|
||||||
|
|
||||||
template <typename T> struct B; // expected-note{{previous template declaration is here}}
|
template <typename T> struct B; // expected-note{{previous template declaration is here}}
|
||||||
template <typename T> requires true // expected-error{{associated constraints differ in template redeclaration}}
|
template <typename T> requires true // expected-error{{requires clause differs in template redeclaration}}
|
||||||
struct B;
|
struct B;
|
||||||
|
|
||||||
template <typename T> requires true // expected-note{{previous template declaration is here}}
|
template <typename T> requires true // expected-note{{previous template declaration is here}}
|
||||||
struct C;
|
struct C;
|
||||||
template <typename T> requires !0 // expected-error{{associated constraints differ in template redeclaration}}
|
template <typename T> requires !0 // expected-error{{requires clause differs in template redeclaration}}
|
||||||
struct C;
|
struct C;
|
||||||
|
|
||||||
} // end namespace diag
|
} // end namespace diag
|
||||||
|
|
@ -33,7 +33,7 @@ struct AA {
|
||||||
struct A;
|
struct A;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T> requires someFunc(T())
|
template <typename U> requires someFunc(U())
|
||||||
struct AA::A { };
|
struct AA::A { };
|
||||||
|
|
||||||
struct AAF {
|
struct AAF {
|
||||||
|
|
@ -47,18 +47,26 @@ namespace diag {
|
||||||
|
|
||||||
template <unsigned N>
|
template <unsigned N>
|
||||||
struct TA {
|
struct TA {
|
||||||
template <template <unsigned> class TT> requires TT<N>::happy // expected-note 2{{previous template declaration is here}}
|
template <template <unsigned> class TT> requires TT<N>::happy // expected-note {{previous template declaration is here}}
|
||||||
struct A;
|
struct A;
|
||||||
|
|
||||||
|
template <template <unsigned> class TT> requires TT<N>::happy // expected-note {{previous template declaration is here}}
|
||||||
|
struct B;
|
||||||
|
|
||||||
struct AF;
|
struct AF;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <unsigned N>
|
template <unsigned N>
|
||||||
template <template <unsigned> class TT> struct TA<N>::A { }; // expected-error{{associated constraints differ in template redeclaration}}
|
template <template <unsigned> class TT> struct TA<N>::A { }; // expected-error{{requires clause differs in template redeclaration}}
|
||||||
|
|
||||||
|
|
||||||
|
template <unsigned N>
|
||||||
|
template <template <unsigned> class TT> requires TT<N + 1>::happy struct TA<N>::B { }; // expected-error{{requires clause differs in template redeclaration}}
|
||||||
|
|
||||||
template <unsigned N>
|
template <unsigned N>
|
||||||
struct TA<N>::AF {
|
struct TA<N>::AF {
|
||||||
template <template <unsigned> class TT> requires TT<N + 0>::happy // expected-error{{associated constraints differ in template redeclaration}}
|
// we do not expect a diagnostic here because the template parameter list is dependent.
|
||||||
|
template <template <unsigned> class TT> requires TT<N + 0>::happy
|
||||||
friend struct TA::A;
|
friend struct TA::A;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
// RUN: %clang_cc1 -std=c++2a -x c++ -verify %s
|
||||||
|
|
||||||
|
namespace nodiag {
|
||||||
|
|
||||||
|
template <typename T> requires bool(T())
|
||||||
|
int A();
|
||||||
|
template <typename U> requires bool(U())
|
||||||
|
int A();
|
||||||
|
|
||||||
|
} // end namespace nodiag
|
||||||
|
|
||||||
|
namespace diag {
|
||||||
|
|
||||||
|
namespace orig {
|
||||||
|
template <typename T> requires true
|
||||||
|
int A();
|
||||||
|
template <typename T>
|
||||||
|
int B();
|
||||||
|
template <typename T> requires true
|
||||||
|
int C();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
int orig::A();
|
||||||
|
// expected-error@-1{{out-of-line declaration of 'A' does not match any declaration in namespace 'diag::orig'}}
|
||||||
|
template <typename T> requires true
|
||||||
|
int orig::B();
|
||||||
|
// expected-error@-1{{out-of-line declaration of 'B' does not match any declaration in namespace 'diag::orig'}}
|
||||||
|
template <typename T> requires !0
|
||||||
|
int orig::C();
|
||||||
|
// expected-error@-1{{out-of-line declaration of 'C' does not match any declaration in namespace 'diag::orig'}}
|
||||||
|
|
||||||
|
} // end namespace diag
|
||||||
|
|
||||||
|
namespace nodiag {
|
||||||
|
|
||||||
|
struct AA {
|
||||||
|
template <typename T> requires someFunc(T())
|
||||||
|
int A();
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T> requires someFunc(T())
|
||||||
|
int AA::A() { return sizeof(T); }
|
||||||
|
|
||||||
|
} // end namespace nodiag
|
||||||
|
|
||||||
|
namespace diag {
|
||||||
|
|
||||||
|
template <unsigned N>
|
||||||
|
struct TA {
|
||||||
|
template <template <unsigned> class TT> requires TT<N>::happy
|
||||||
|
int A();
|
||||||
|
};
|
||||||
|
|
||||||
|
template <unsigned N>
|
||||||
|
template <template <unsigned> class TT> int TA<N>::A() { return sizeof(TT<N>); }
|
||||||
|
// expected-error@-1{{out-of-line definition of 'A' does not match any declaration in 'TA<N>'}}
|
||||||
|
|
||||||
|
} // end namespace diag
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
// RUN: %clang_cc1 -std=c++2a -x c++ -verify %s
|
||||||
|
|
||||||
|
namespace nodiag {
|
||||||
|
|
||||||
|
struct B {
|
||||||
|
template <typename T> requires bool(T())
|
||||||
|
static int A;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename U> requires bool(U())
|
||||||
|
int B::A = int(U());
|
||||||
|
|
||||||
|
} // end namespace nodiag
|
||||||
|
|
||||||
|
namespace diag {
|
||||||
|
|
||||||
|
struct B {
|
||||||
|
template <typename T> requires bool(T()) // expected-note{{previous template declaration is here}}
|
||||||
|
static int A;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename U> requires !bool(U()) // expected-error{{requires clause differs in template redeclaration}}
|
||||||
|
int B::A = int(U());
|
||||||
|
|
||||||
|
} // end namespace diag
|
||||||
Loading…
Reference in New Issue