saar.raz updated this revision to Diff 129297.
saar.raz added a comment.
- Fixed wrong if that would cause valid instantiated requires clauses to not be
accepted.
Repository:
rC Clang
https://reviews.llvm.org/D41284
Files:
include/clang/AST/DeclTemplate.h
include/clang/AST/RecursiveASTVisitor.h
include/clang/Sema/Sema.h
lib/AST/DeclTemplate.cpp
lib/Sema/SemaTemplate.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
lib/Serialization/ASTReader.cpp
lib/Serialization/ASTReaderDecl.cpp
lib/Serialization/ASTWriter.cpp
lib/Serialization/ASTWriterDecl.cpp
test/CXX/concepts-ts/temp/temp.constr/temp.constr.decl/class-template-decl.cpp
test/CXX/concepts-ts/temp/temp.constr/temp.constr.decl/func-template-decl.cpp
test/CXX/concepts-ts/temp/temp.constr/temp.constr.decl/var-template-decl.cpp
Index: test/CXX/concepts-ts/temp/temp.constr/temp.constr.decl/var-template-decl.cpp
===================================================================
--- /dev/null
+++ test/CXX/concepts-ts/temp/temp.constr/temp.constr.decl/var-template-decl.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -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{{associated constraints differ in template redeclaration}}
+int B::A = int(U());
+
+} // end namespace diag
\ No newline at end of file
Index: test/CXX/concepts-ts/temp/temp.constr/temp.constr.decl/func-template-decl.cpp
===================================================================
--- test/CXX/concepts-ts/temp/temp.constr/temp.constr.decl/func-template-decl.cpp
+++ test/CXX/concepts-ts/temp/temp.constr/temp.constr.decl/func-template-decl.cpp
@@ -1,65 +1,52 @@
-// RUN: %clang_cc1 -std=c++14 -fconcepts-ts -x c++ -verify %s
+// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ -verify %s
namespace nodiag {
template <typename T> requires bool(T())
-struct A;
+int A();
template <typename U> requires bool(U())
-struct A;
+int A();
} // end namespace nodiag
namespace diag {
template <typename T> requires true // expected-note{{previous template declaration is here}}
-struct A;
-template <typename T> struct A; // expected-error{{associated constraints differ in template redeclaration}}
+int A();
+template <typename T> int A(); // expected-error{{associated constraints differ in template redeclaration}}
-template <typename T> struct B; // expected-note{{previous template declaration is here}}
+template <typename T> int B(); // expected-note{{previous template declaration is here}}
template <typename T> requires true // expected-error{{associated constraints differ in template redeclaration}}
-struct B;
+int B();
template <typename T> requires true // expected-note{{previous template declaration is here}}
-struct C;
+int C();
template <typename T> requires !0 // expected-error{{associated constraints differ in template redeclaration}}
-struct C;
+int C();
} // end namespace diag
namespace nodiag {
struct AA {
template <typename T> requires someFunc(T())
- struct A;
+ int A();
};
template <typename T> requires someFunc(T())
-struct AA::A { };
-
-struct AAF {
- template <typename T> requires someFunc(T())
- friend struct AA::A;
-};
+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 // expected-note 2{{previous template declaration is here}}
- struct A;
-
- struct AF;
+ template <template <unsigned> class TT> requires TT<N>::happy // expected-note{{previous template declaration is here}}
+ int A();
};
template <unsigned N>
-template <template <unsigned> class TT> struct TA<N>::A { }; // expected-error{{associated constraints differ in template redeclaration}}
-
-template <unsigned N>
-struct TA<N>::AF {
- template <template <unsigned> class TT> requires TT<N + 0>::happy // expected-error{{associated constraints differ in template redeclaration}}
- friend struct TA::A;
-};
+template <template <unsigned> class TT> int TA<N>::A() { return sizeof(TT<N>); } // expected-error{{associated constraints differ in template redeclaration}}
} // end namespace diag
Index: test/CXX/concepts-ts/temp/temp.constr/temp.constr.decl/class-template-decl.cpp
===================================================================
--- test/CXX/concepts-ts/temp/temp.constr/temp.constr.decl/class-template-decl.cpp
+++ test/CXX/concepts-ts/temp/temp.constr/temp.constr.decl/class-template-decl.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++14 -fconcepts-ts -x c++ -verify %s
+// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -x c++ -verify %s
namespace nodiag {
@@ -33,7 +33,7 @@
struct A;
};
-template <typename T> requires someFunc(T())
+template <typename U> requires someFunc(U())
struct AA::A { };
struct AAF {
@@ -47,18 +47,26 @@
template <unsigned N>
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;
+ template <template <unsigned> class TT> requires TT<N>::happy // expected-note {{previous template declaration is here}}
+ struct B;
+
struct AF;
};
template <unsigned N>
template <template <unsigned> class TT> struct TA<N>::A { }; // expected-error{{associated constraints differ in template redeclaration}}
+
+template <unsigned N>
+template <template <unsigned> class TT> requires TT<N + 1>::happy struct TA<N>::B { }; // expected-error{{associated constraints differ in template redeclaration}}
+
template <unsigned N>
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;
};
Index: lib/Serialization/ASTWriterDecl.cpp
===================================================================
--- lib/Serialization/ASTWriterDecl.cpp
+++ lib/Serialization/ASTWriterDecl.cpp
@@ -1402,6 +1402,12 @@
Record.AddDeclRef(D->getInstantiatedFromMemberTemplate());
if (D->getInstantiatedFromMemberTemplate())
Record.push_back(D->isMemberSpecialization());
+
+ Expr *AssociatedConstraints = D->getAssociatedConstraints();
+ Record.push_back(AssociatedConstraints != nullptr);
+ if (AssociatedConstraints) {
+ Record.AddStmt(AssociatedConstraints);
+ }
}
VisitTemplateDecl(D);
@@ -1463,6 +1469,11 @@
if (D->getPreviousDecl() == nullptr) {
Record.AddDeclRef(D->getInstantiatedFromMember());
Record.push_back(D->isMemberSpecialization());
+ Expr *AssociatedConstraints = D->getAssociatedConstraints();
+ Record.push_back(AssociatedConstraints != nullptr);
+ if (AssociatedConstraints) {
+ Record.AddStmt(AssociatedConstraints);
+ }
}
Code = serialization::DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION;
@@ -1523,6 +1534,11 @@
if (D->getPreviousDecl() == nullptr) {
Record.AddDeclRef(D->getInstantiatedFromMember());
Record.push_back(D->isMemberSpecialization());
+ Expr *AssociatedConstraints = D->getAssociatedConstraints();
+ Record.push_back(AssociatedConstraints != nullptr);
+ if (AssociatedConstraints) {
+ Record.AddStmt(AssociatedConstraints);
+ }
}
Code = serialization::DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION;
Index: lib/Serialization/ASTWriter.cpp
===================================================================
--- lib/Serialization/ASTWriter.cpp
+++ lib/Serialization/ASTWriter.cpp
@@ -5850,10 +5850,16 @@
AddSourceLocation(TemplateParams->getTemplateLoc());
AddSourceLocation(TemplateParams->getLAngleLoc());
AddSourceLocation(TemplateParams->getRAngleLoc());
- // TODO: Concepts
+
Record->push_back(TemplateParams->size());
for (const auto &P : *TemplateParams)
- AddDeclRef(P);
+ AddDeclRef(P); // TODO: Concepts - constrained parameters.
+ if (const Expr *RequiresClause = TemplateParams->getRequiresClause()) {
+ Record->push_back(true);
+ AddStmt(const_cast<Expr*>(RequiresClause));
+ } else {
+ Record->push_back(false);
+ }
}
/// \brief Emit a template argument list.
Index: lib/Serialization/ASTReaderDecl.cpp
===================================================================
--- lib/Serialization/ASTReaderDecl.cpp
+++ lib/Serialization/ASTReaderDecl.cpp
@@ -1965,7 +1965,6 @@
DeclID PatternID = ReadDeclID();
NamedDecl *TemplatedDecl = cast_or_null<NamedDecl>(Reader.GetDecl(PatternID));
TemplateParameterList *TemplateParams = Record.readTemplateParameterList();
- // FIXME handle associated constraints
D->init(TemplatedDecl, TemplateParams);
return PatternID;
@@ -1991,6 +1990,7 @@
// If this is the first declaration of the template, fill in the information
// for the 'common' pointer.
+ Expr *AssociatedConstraints = nullptr;
if (ThisDeclID == Redecl.getFirstID()) {
if (RedeclarableTemplateDecl *RTD
= ReadDeclAs<RedeclarableTemplateDecl>()) {
@@ -2000,11 +2000,23 @@
if (Record.readInt())
D->setMemberSpecialization();
}
+ bool HasAssociatedConstraints = Record.readInt();
+ if (HasAssociatedConstraints) {
+ AssociatedConstraints = Record.readExpr();
+ }
}
DeclID PatternID = VisitTemplateDecl(D);
D->IdentifierNamespace = Record.readInt();
+ D->TemplateParams.setInt(true);
+ if (AssociatedConstraints) {
+ auto *CTDI = new (Reader.getContext()) ConstrainedTemplateDeclInfo;
+ CTDI->setTemplateParameters(D->getTemplateParameters());
+ CTDI->setAssociatedConstraints(AssociatedConstraints);
+ D->TemplateParams.setPointer(CTDI);
+ }
+
mergeRedeclarable(D, Redecl, PatternID);
// If we merged the template with a prior declaration chain, merge the common
@@ -2132,14 +2144,24 @@
ClassTemplatePartialSpecializationDecl *D) {
RedeclarableResult Redecl = VisitClassTemplateSpecializationDeclImpl(D);
- D->TemplateParams = Record.readTemplateParameterList();
+ TemplateParameterList *Params = Record.readTemplateParameterList();
+ D->TemplateParams.setPointer(Params);
D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo();
// These are read/set from/to the first declaration.
if (ThisDeclID == Redecl.getFirstID()) {
D->InstantiatedFromMember.setPointer(
ReadDeclAs<ClassTemplatePartialSpecializationDecl>());
D->InstantiatedFromMember.setInt(Record.readInt());
+ bool HasAssociatedConstraints = Record.readInt();
+ D->TemplateParams.setInt(true);
+ if (HasAssociatedConstraints) {
+ Expr *AssociatedConstraints = Record.readExpr();
+ auto *CTDI = new (Reader.getContext()) ConstrainedTemplateDeclInfo;
+ CTDI->setTemplateParameters(Params);
+ CTDI->setAssociatedConstraints(AssociatedConstraints);
+ D->TemplateParams.setPointer(CTDI);
+ }
}
}
@@ -2233,14 +2255,25 @@
VarTemplatePartialSpecializationDecl *D) {
RedeclarableResult Redecl = VisitVarTemplateSpecializationDeclImpl(D);
- D->TemplateParams = Record.readTemplateParameterList();
+ TemplateParameterList *Params = Record.readTemplateParameterList();
+ D->TemplateParams.setPointer(Params);
D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo();
// These are read/set from/to the first declaration.
if (ThisDeclID == Redecl.getFirstID()) {
D->InstantiatedFromMember.setPointer(
ReadDeclAs<VarTemplatePartialSpecializationDecl>());
D->InstantiatedFromMember.setInt(Record.readInt());
+
+ bool HasAssociatedConstraints = Record.readInt();
+ D->TemplateParams.setInt(true);
+ if (HasAssociatedConstraints) {
+ Expr *AssociatedConstraints = Record.readExpr();
+ auto *CTDI = new (Reader.getContext()) ConstrainedTemplateDeclInfo;
+ CTDI->setTemplateParameters(Params);
+ CTDI->setAssociatedConstraints(AssociatedConstraints);
+ D->TemplateParams.setPointer(CTDI);
+ }
}
}
Index: lib/Serialization/ASTReader.cpp
===================================================================
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -8664,10 +8664,13 @@
Params.reserve(NumParams);
while (NumParams--)
Params.push_back(ReadDeclAs<NamedDecl>(F, Record, Idx));
+ // TODO: Concepts: Constrained parameters
+
+ bool HasRequiresClause = Record[Idx++];
+ Expr *RequiresClause = HasRequiresClause ? ReadExpr(F) : nullptr;
- // TODO: Concepts
TemplateParameterList *TemplateParams = TemplateParameterList::Create(
- getContext(), TemplateLoc, LAngleLoc, Params, RAngleLoc, nullptr);
+ getContext(), TemplateLoc, LAngleLoc, Params, RAngleLoc, RequiresClause);
return TemplateParams;
}
Index: lib/Sema/SemaTemplateInstantiateDecl.cpp
===================================================================
--- lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3138,14 +3138,19 @@
if (Invalid)
return nullptr;
- // Note: we substitute into associated constraints later
- Expr *const UninstantiatedRequiresClause = L->getRequiresClause();
+ 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::Create(SemaRef.Context, L->getTemplateLoc(),
L->getLAngleLoc(), Params,
- L->getRAngleLoc(),
- UninstantiatedRequiresClause);
+ L->getRAngleLoc(), InstRequiresClause);
return InstL;
}
Index: lib/Sema/SemaTemplate.cpp
===================================================================
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -45,24 +45,18 @@
return SourceRange(Ps[0]->getTemplateLoc(), Ps[N-1]->getRAngleLoc());
}
-namespace clang {
-/// \brief [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();
+bool Sema::CheckRedeclarationConstraintMatch(const Expr *OldAC,
+ const Expr *NewAC) {
+ if (!(NewAC || OldAC))
+ return true; // Nothing to check; no mismatch.
+ if (NewAC && OldAC) {
+ llvm::FoldingSetNodeID OldACInfo, NewACInfo;
+ NewAC->Profile(NewACInfo, Context, /*Canonical=*/true);
+ OldAC->Profile(OldACInfo, Context, /*Canonical=*/true);
+ if (NewACInfo == OldACInfo)
+ return true; // All good; no mismatch.
+ }
+ return false;
}
/// \brief Determine whether the declaration found is acceptable as the name
@@ -1269,9 +1263,6 @@
}
}
- // TODO Memory management; associated constraints are not always stored.
- Expr *const CurAC = formAssociatedConstraints(TemplateParams, nullptr);
-
if (PrevClassTemplate) {
// Ensure that the template parameter lists are compatible. Skip this check
// for a friend in a dependent context: the template parameter list itself
@@ -1283,29 +1274,6 @@
TPL_TemplateMatch))
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->getLocStart() : NameLoc,
- diag::err_template_different_associated_constraints);
- Diag(PrevAC ? PrevAC->getLocStart() : PrevClassTemplate->getLocation(),
- diag::note_template_prev_declaration) << /*declaration*/0;
- return true;
- }
-
// C++ [temp.class]p4:
// In a redeclaration, partial specialization, explicit
// specialization or explicit instantiation of a class template,
@@ -1408,15 +1376,10 @@
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::Create(Context, SemanticContext, NameLoc,
DeclarationName(Name), TemplateParams,
- NewClass, ACtoAttach);
+ NewClass);
if (ShouldAddRedecl)
NewTemplate->setPreviousDecl(PrevClassTemplate);
@@ -2001,6 +1964,19 @@
if (OldParams)
OldParam = OldParams->begin();
+ // TODO: Concepts: Replace getRequiresClause with getAssociatedConstraints
+ // when we have it.
+ if (OldParams &&
+ !CheckRedeclarationConstraintMatch(OldParams->getRequiresClause(),
+ NewParams->getRequiresClause())) {
+ Diag(NewParams->getTemplateLoc(),
+ diag::err_template_different_associated_constraints);
+ Diag(OldParams->getTemplateLoc(), diag::note_template_prev_declaration)
+ << /*declaration*/0;
+
+ Invalid = true;
+ }
+
bool RemoveDefaultArguments = false;
for (TemplateParameterList::iterator NewParam = NewParams->begin(),
NewParamEnd = NewParams->end();
@@ -2181,16 +2157,14 @@
// We were missing some default arguments at the end of the list, so remove
// all of the default arguments.
if (RemoveDefaultArguments) {
- for (TemplateParameterList::iterator NewParam = NewParams->begin(),
- NewParamEnd = NewParams->end();
- NewParam != NewParamEnd; ++NewParam) {
- if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*NewParam))
+ for (NamedDecl *NewParam : *NewParams) {
+ if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(NewParam))
TTP->removeDefaultArgument();
else if (NonTypeTemplateParmDecl *NTTP
- = dyn_cast<NonTypeTemplateParmDecl>(*NewParam))
+ = dyn_cast<NonTypeTemplateParmDecl>(NewParam))
NTTP->removeDefaultArgument();
else
- cast<TemplateTemplateParmDecl>(*NewParam)->removeDefaultArgument();
+ cast<TemplateTemplateParmDecl>(NewParam)->removeDefaultArgument();
}
}
Index: lib/AST/DeclTemplate.cpp
===================================================================
--- lib/AST/DeclTemplate.cpp
+++ lib/AST/DeclTemplate.cpp
@@ -146,6 +146,65 @@
} // namespace clang
+static ConstrainedTemplateDeclInfo *
+collectAssociatedConstraints(ASTContext& C, TemplateParameterList *Params) {
+ // TODO: Instead of calling getRequiresClause - write and call a
+ // TemplateParameterList member function calculateAssociatedConstraints, which
+ // will also fetch constraint-expressions from constrained-parameters.
+ Expr *AssociatedConstraints = Params->getRequiresClause();
+ // TODO: Collect function requires clause, if any.
+ if (AssociatedConstraints) {
+ ConstrainedTemplateDeclInfo *CTDI = new (C) ConstrainedTemplateDeclInfo;
+ CTDI->setAssociatedConstraints(AssociatedConstraints);
+ CTDI->setTemplateParameters(Params);
+ return CTDI;
+ }
+ return nullptr;
+}
+
+// This function exists outside TemplateDecl because
+// '*TemplatePartialSpecializationDecls' need this code too, and are not derived
+// from the former.
+Expr *
+getOrCollectAssociatedConstraints(ASTContext& C,
+ llvm::PointerIntPair<
+ llvm::PointerUnion<TemplateParameterList *,
+ ConstrainedTemplateDeclInfo *>,
+ 1, bool>& TemplateParamsMember) {
+ if (!TemplateParamsMember.getInt()) {
+ TemplateParamsMember.setInt(true);
+ ConstrainedTemplateDeclInfo *CTDI =
+ collectAssociatedConstraints(C, TemplateParamsMember.getPointer()
+ .get<TemplateParameterList*>());
+ if (CTDI) {
+ TemplateParamsMember.setPointer(CTDI);
+ return CTDI->getAssociatedConstraints();
+ }
+ return nullptr;
+ }
+ const auto *const CTDI = TemplateParamsMember.getPointer()
+ .dyn_cast<ConstrainedTemplateDeclInfo *>();
+ return CTDI ? CTDI->getAssociatedConstraints() : nullptr;
+}
+
+//===----------------------------------------------------------------------===//
+// 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, false) {}
+
+
+Expr *TemplateDecl::getAssociatedConstraints() {
+ return getOrCollectAssociatedConstraints(getASTContext(),
+ cast<TemplateDecl>(getCanonicalDecl())->TemplateParams);
+}
+
+void TemplateDecl::anchor() {}
+
//===----------------------------------------------------------------------===//
// RedeclarableTemplateDecl Implementation
//===----------------------------------------------------------------------===//
@@ -308,19 +367,10 @@
SourceLocation L,
DeclarationName Name,
TemplateParameterList *Params,
- NamedDecl *Decl,
- Expr *AssociatedConstraints) {
+ NamedDecl *Decl) {
AdoptTemplateParameterList(Params, cast<DeclContext>(Decl));
- if (!AssociatedConstraints) {
- return new (C, DC) ClassTemplateDecl(C, DC, L, Name, Params, Decl);
- }
-
- ConstrainedTemplateDeclInfo *const CTDI = new (C) ConstrainedTemplateDeclInfo;
- ClassTemplateDecl *const New =
- new (C, DC) ClassTemplateDecl(CTDI, C, DC, L, Name, Params, Decl);
- New->setAssociatedConstraints(AssociatedConstraints);
- return New;
+ return new (C, DC) ClassTemplateDecl(C, DC, L, Name, Params, Decl);
}
ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C,
@@ -680,12 +730,6 @@
POI);
}
-//===----------------------------------------------------------------------===//
-// TemplateDecl Implementation
-//===----------------------------------------------------------------------===//
-
-void TemplateDecl::anchor() {}
-
//===----------------------------------------------------------------------===//
// ClassTemplateSpecializationDecl Implementation
//===----------------------------------------------------------------------===//
@@ -838,8 +882,8 @@
ClassTemplatePartialSpecialization,
TK, DC, StartLoc, IdLoc,
SpecializedTemplate, Args, PrevDecl),
- TemplateParams(Params), ArgsAsWritten(ArgInfos),
- InstantiatedFromMember(nullptr, false) {
+ TemplateParams(Params, false),
+ ArgsAsWritten(ArgInfos), InstantiatedFromMember(nullptr, false) {
AdoptTemplateParameterList(Params, this);
}
@@ -876,6 +920,12 @@
return Result;
}
+Expr* ClassTemplatePartialSpecializationDecl::getAssociatedConstraints() {
+ return getOrCollectAssociatedConstraints(getASTContext(),
+ cast<ClassTemplatePartialSpecializationDecl>(getCanonicalDecl())
+ ->TemplateParams);
+}
+
//===----------------------------------------------------------------------===//
// FriendTemplateDecl Implementation
//===----------------------------------------------------------------------===//
@@ -1131,7 +1181,7 @@
: VarTemplateSpecializationDecl(VarTemplatePartialSpecialization, Context,
DC, StartLoc, IdLoc, SpecializedTemplate, T,
TInfo, S, Args),
- TemplateParams(Params), ArgsAsWritten(ArgInfos),
+ TemplateParams(Params, false), ArgsAsWritten(ArgInfos),
InstantiatedFromMember(nullptr, false) {
// TODO: The template parameters should be in DC by now. Verify.
// AdoptTemplateParameterList(Params, DC);
@@ -1161,6 +1211,12 @@
return new (C, ID) VarTemplatePartialSpecializationDecl(C);
}
+Expr* VarTemplatePartialSpecializationDecl::getAssociatedConstraints() {
+ return getOrCollectAssociatedConstraints(getASTContext(),
+ cast<VarTemplatePartialSpecializationDecl>(getCanonicalDecl())
+ ->TemplateParams);
+}
+
static TemplateParameterList *
createMakeIntegerSeqParameterList(const ASTContext &C, DeclContext *DC) {
// typename T
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -5580,7 +5580,12 @@
/// A diagnostic is emmited if it is not, and false is returned.
bool CheckConstraintExpression(Expr *CE);
- // ParseObjCStringLiteral - Parse Objective-C string literals.
+ /// \brief 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(const Expr *OldAC, const Expr *NewAC);
+
+ // ParseObjCStringLiteral - Parse Objective-C string literals.
ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
ArrayRef<Expr *> Strings);
Index: include/clang/AST/RecursiveASTVisitor.h
===================================================================
--- include/clang/AST/RecursiveASTVisitor.h
+++ include/clang/AST/RecursiveASTVisitor.h
@@ -1594,9 +1594,11 @@
bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper(
TemplateParameterList *TPL) {
if (TPL) {
- for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end();
- I != E; ++I) {
- TRY_TO(TraverseDecl(*I));
+ for (NamedDecl *D : *TPL) {
+ TRY_TO(TraverseDecl(D));
+ }
+ if (Expr *RequiresClause = TPL->getRequiresClause()) {
+ TRY_TO(TraverseStmt(RequiresClause));
}
}
return true;
Index: include/clang/AST/DeclTemplate.h
===================================================================
--- include/clang/AST/DeclTemplate.h
+++ include/clang/AST/DeclTemplate.h
@@ -368,8 +368,6 @@
/// \brief Stores the template parameter list and associated constraints for
/// \c TemplateDecl objects that track associated constraints.
class ConstrainedTemplateDeclInfo {
- friend TemplateDecl;
-
public:
ConstrainedTemplateDeclInfo() = default;
@@ -379,13 +377,14 @@
Expr *getAssociatedConstraints() const { return AssociatedConstraints; }
-protected:
void setTemplateParameters(TemplateParameterList *TParams) {
TemplateParams = TParams;
}
void setAssociatedConstraints(Expr *AC) { AssociatedConstraints = AC; }
+protected:
+
TemplateParameterList *TemplateParams = nullptr;
Expr *AssociatedConstraints = nullptr;
};
@@ -400,54 +399,33 @@
void anchor() override;
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.
// 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,
TemplateParameterList *Params)
- : TemplateDecl(nullptr, DK, DC, L, Name, Params) {}
-
- // 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) {}
+ : TemplateDecl(DK, DC, L, Name, Params, nullptr) {}
public:
+ friend class ASTDeclReader;
+ friend class ASTDeclWriter;
+
/// Get the list of template parameters
TemplateParameterList *getTemplateParameters() const {
const auto *const CTDI =
- TemplateParams.dyn_cast<ConstrainedTemplateDeclInfo *>();
+ TemplateParams.getPointer().dyn_cast<ConstrainedTemplateDeclInfo *>();
return CTDI ? CTDI->getTemplateParameters()
- : TemplateParams.get<TemplateParameterList *>();
- }
-
- /// Get the constraint-expression from the associated requires-clause (if any)
- const Expr *getRequiresClause() const {
- const TemplateParameterList *const TP = getTemplateParameters();
- return TP ? TP->getRequiresClause() : nullptr;
+ : TemplateParams.getPointer().get<TemplateParameterList *>();
}
- Expr *getAssociatedConstraints() const {
- const TemplateDecl *const C = cast<TemplateDecl>(getCanonicalDecl());
- const auto *const CTDI =
- C->TemplateParams.dyn_cast<ConstrainedTemplateDeclInfo *>();
- return CTDI ? CTDI->getAssociatedConstraints() : nullptr;
- }
+ /// \brief Get the total constraint-expression associated with this template,
+ /// including constraint-expressions derived from the requires-clause,
+ /// trailing requires-clause (for functions and methods) and constrained
+ /// template parameters.
+ Expr *getAssociatedConstraints();
/// Get the underlying, templated declaration.
NamedDecl *getTemplatedDecl() const { return TemplatedDecl; }
@@ -466,38 +444,32 @@
protected:
NamedDecl *TemplatedDecl;
- /// \brief 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;
+ /// \brief If the int part is true, this declaration is the canonical
+ /// declaration, and the associated constraints for it have been calculated.
+ /// If any constraints were found, the pointer part will contain a
+ /// \c ConstrainedTemplateDeclInfo with the collected associated constraints.
+ /// Otherwise, this will just contain the template parameter list.
+ llvm::PointerIntPair<llvm::PointerUnion<TemplateParameterList *,
+ ConstrainedTemplateDeclInfo *>, 1,
+ bool> TemplateParams;
void setTemplateParameters(TemplateParameterList *TParams) {
- if (auto *const CTDI =
- TemplateParams.dyn_cast<ConstrainedTemplateDeclInfo *>()) {
+ if (auto *const CTDI = TemplateParams.getPointer()
+ .dyn_cast<ConstrainedTemplateDeclInfo *>()) {
CTDI->setTemplateParameters(TParams);
} else {
- TemplateParams = TParams;
+ TemplateParams.setPointer(TParams);
}
}
- void setAssociatedConstraints(Expr *AC) {
- assert(isCanonicalDecl() &&
- "Attaching associated constraints to non-canonical Decl");
- TemplateParams.get<ConstrainedTemplateDeclInfo *>()
- ->setAssociatedConstraints(AC);
- }
-
public:
/// \brief Initialize the underlying templated declaration and
/// template parameters.
void init(NamedDecl *templatedDecl, TemplateParameterList* templateParams) {
assert(!TemplatedDecl && "TemplatedDecl already set!");
assert(!TemplateParams && "TemplateParams already set!");
TemplatedDecl = templatedDecl;
- TemplateParams = templateParams;
+ TemplateParams.setPointer(templateParams);
}
};
@@ -822,17 +794,10 @@
virtual CommonBase *newCommon(ASTContext &C) const = 0;
// 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,
SourceLocation L, DeclarationName Name,
TemplateParameterList *Params, NamedDecl *Decl)
- : RedeclarableTemplateDecl(nullptr, DK, C, DC, L, Name, Params, Decl) {}
+ : TemplateDecl(DK, DC, L, Name, Params, Decl), redeclarable_base(C) {}
public:
friend class ASTDeclReader;
@@ -1897,8 +1862,14 @@
class ClassTemplatePartialSpecializationDecl
: public ClassTemplateSpecializationDecl {
- /// \brief The list of template parameters
- TemplateParameterList* TemplateParams = nullptr;
+ /// \brief If the int part is true, this declaration is the canonical
+ /// declaration, and the associated constraints for it have been calculated.
+ /// If any constraints were found, the pointer part will contain a
+ /// \c ConstrainedTemplateDeclInfo with the collected associated constraints.
+ /// Otherwise, this will just contain the template parameter list.
+ llvm::PointerIntPair<llvm::PointerUnion<TemplateParameterList *,
+ ConstrainedTemplateDeclInfo *>, 1,
+ bool> TemplateParams;
/// \brief The source info for the template arguments as written.
/// FIXME: redundant with TypeAsWritten?
@@ -1953,9 +1924,18 @@
/// Get the list of template parameters
TemplateParameterList *getTemplateParameters() const {
- return TemplateParams;
+ const auto *const CTDI =
+ TemplateParams.getPointer().dyn_cast<ConstrainedTemplateDeclInfo *>();
+ return CTDI ? CTDI->getTemplateParameters()
+ : TemplateParams.getPointer().get<TemplateParameterList *>();
}
+ /// \brief Get the total constraint-expression associated with this template,
+ /// including constraint-expressions derived from the requires-clause,
+ /// trailing requires-clause (for functions and methods) and constrained
+ /// template parameters.
+ Expr *getAssociatedConstraints();
+
/// Get the template arguments as written.
const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
return ArgsAsWritten;
@@ -2084,16 +2064,10 @@
llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &
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,
DeclarationName Name, TemplateParameterList *Params,
NamedDecl *Decl)
- : ClassTemplateDecl(nullptr, C, DC, L, Name, Params, Decl) {}
+ : RedeclarableTemplateDecl(ClassTemplate, C, DC, L, Name, Params, Decl) {}
CommonBase *newCommon(ASTContext &C) const override;
@@ -2125,8 +2099,7 @@
SourceLocation L,
DeclarationName Name,
TemplateParameterList *Params,
- NamedDecl *Decl,
- Expr *AssociatedConstraints = nullptr);
+ NamedDecl *Decl);
/// \brief Create an empty class template node.
static ClassTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
@@ -2740,8 +2713,14 @@
class VarTemplatePartialSpecializationDecl
: public VarTemplateSpecializationDecl {
- /// \brief The list of template parameters
- TemplateParameterList *TemplateParams = nullptr;
+ /// \brief If the int part is true, this declaration is the canonical
+ /// declaration, and the associated constraints for it have been calculated.
+ /// If any constraints were found, the pointer part will contain a
+ /// \c ConstrainedTemplateDeclInfo with the collected associated constraints.
+ /// Otherwise, this will just contain the template parameter list.
+ llvm::PointerIntPair<llvm::PointerUnion<TemplateParameterList *,
+ ConstrainedTemplateDeclInfo *>, 1,
+ bool> TemplateParams;
/// \brief The source info for the template arguments as written.
/// FIXME: redundant with TypeAsWritten?
@@ -2791,14 +2770,23 @@
/// Get the list of template parameters
TemplateParameterList *getTemplateParameters() const {
- return TemplateParams;
+ const auto *const CTDI =
+ TemplateParams.getPointer().dyn_cast<ConstrainedTemplateDeclInfo *>();
+ return CTDI ? CTDI->getTemplateParameters()
+ : TemplateParams.getPointer().get<TemplateParameterList *>();
}
/// Get the template arguments as written.
const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
return ArgsAsWritten;
}
+ /// \brief Get the total constraint-expression associated with this template,
+ /// including constraint-expressions derived from the requires-clause,
+ /// trailing requires-clause (for functions and methods) and constrained
+ /// template parameters.
+ Expr *getAssociatedConstraints();
+
/// \brief Retrieve the member variable template partial specialization from
/// which this particular variable template partial specialization was
/// instantiated.
@@ -3037,11 +3025,9 @@
protected:
Expr *ConstraintExpr;
- ConceptDecl(DeclContext *DC,
- SourceLocation L, DeclarationName Name,
- TemplateParameterList *Params,
- Expr *ConstraintExpr)
- : TemplateDecl(nullptr, Concept, DC, L, Name, Params),
+ ConceptDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
+ TemplateParameterList *Params, Expr *ConstraintExpr)
+ : TemplateDecl(Concept, DC, L, Name, Params),
ConstraintExpr(ConstraintExpr) {};
public:
static ConceptDecl *Create(ASTContext &C, DeclContext *DC,
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits