saar.raz updated this revision to Diff 127163.
saar.raz added a comment.

- Added requires clause matching for all kinds of template redeclarations 
instead of just classes.


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()) {
+      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
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to