r374938 - [Concept] Associated Constraints Infrastructure

Saar Raz via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 15 11:44:06 PDT 2019


Author: saar.raz
Date: Tue Oct 15 11:44:06 2019
New Revision: 374938

URL: http://llvm.org/viewvc/llvm-project?rev=374938&view=rev
Log:
[Concept] Associated Constraints Infrastructure

Add code to correctly calculate the associated constraints of a template (no enforcement yet).
D41284 on Phabricator.


Added:
    cfe/trunk/test/CXX/temp/concept/p4.cpp
    cfe/trunk/test/CXX/temp/temp.constr/temp.constr.decl/func-template-decl.cpp
    cfe/trunk/test/CXX/temp/temp.constr/temp.constr.decl/var-template-decl.cpp
Modified:
    cfe/trunk/include/clang/AST/ASTNodeTraverser.h
    cfe/trunk/include/clang/AST/DeclTemplate.h
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/ASTContext.cpp
    cfe/trunk/lib/AST/DeclTemplate.cpp
    cfe/trunk/lib/Sema/SemaConcept.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/lib/Serialization/ASTReader.cpp
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
    cfe/trunk/test/CXX/temp/temp.constr/temp.constr.decl/class-template-decl.cpp

Modified: cfe/trunk/include/clang/AST/ASTNodeTraverser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTNodeTraverser.h?rev=374938&r1=374937&r2=374938&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTNodeTraverser.h (original)
+++ cfe/trunk/include/clang/AST/ASTNodeTraverser.h Tue Oct 15 11:44:06 2019
@@ -237,6 +237,9 @@ public:
 
     for (const auto &TP : *TPL)
       Visit(TP);
+
+    if (const Expr *RC = TPL->getRequiresClause())
+      Visit(RC);
   }
 
   void

Modified: cfe/trunk/include/clang/AST/DeclTemplate.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=374938&r1=374937&r2=374938&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
+++ cfe/trunk/include/clang/AST/DeclTemplate.h Tue Oct 15 11:44:06 2019
@@ -168,6 +168,16 @@ public:
     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 getLAngleLoc() const { return LAngleLoc; }
   SourceLocation getRAngleLoc() const { return RAngleLoc; }
@@ -369,33 +379,7 @@ public:
 // Kinds of Templates
 //===----------------------------------------------------------------------===//
 
-/// Stores the template parameter list and associated constraints for
-/// \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.,
+/// \brief The base class of all kinds of template declarations (e.g.,
 /// class, function, etc.).
 ///
 /// The TemplateDecl class stores the list of template parameters and a
@@ -404,55 +388,33 @@ class TemplateDecl : public NamedDecl {
   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 *>();
-    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;
-  }
-
-  Expr *getAssociatedConstraints() const {
-    const auto *const C = cast<TemplateDecl>(getCanonicalDecl());
-    const auto *const CTDI =
-        C->TemplateParams.dyn_cast<ConstrainedTemplateDeclInfo *>();
-    return CTDI ? CTDI->getAssociatedConstraints() : nullptr;
+    return TemplateParams;
   }
 
+  /// \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.
+  void getAssociatedConstraints(llvm::SmallVectorImpl<const Expr *> &AC) const;
+
+  bool hasAssociatedConstraints() const;
+
   /// Get the underlying, templated declaration.
   NamedDecl *getTemplatedDecl() const { return TemplatedDecl; }
 
@@ -470,29 +432,10 @@ public:
 
 protected:
   NamedDecl *TemplatedDecl;
-
-  /// 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;
+  TemplateParameterList *TemplateParams;
 
   void setTemplateParameters(TemplateParameterList *TParams) {
-    if (auto *const CTDI =
-            TemplateParams.dyn_cast<ConstrainedTemplateDeclInfo *>()) {
-      CTDI->setTemplateParameters(TParams);
-    } else {
-      TemplateParams = TParams;
-    }
-  }
-
-  void setAssociatedConstraints(Expr *AC) {
-    assert(isCanonicalDecl() &&
-           "Attaching associated constraints to non-canonical Decl");
-    TemplateParams.get<ConstrainedTemplateDeclInfo *>()
-        ->setAssociatedConstraints(AC);
+    TemplateParams = TParams;
   }
 
 public:
@@ -889,17 +832,10 @@ protected:
   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;
@@ -2026,6 +1962,20 @@ public:
     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.
   const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const {
     return ArgsAsWritten;
@@ -2145,16 +2095,10 @@ protected:
   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;
 
@@ -2180,14 +2124,12 @@ public:
     return getTemplatedDecl()->isThisDeclarationADefinition();
   }
 
-  // FIXME: remove default argument for AssociatedConstraints
-  /// Create a class template node.
+  /// \brief Create a class template node.
   static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC,
                                    SourceLocation L,
                                    DeclarationName Name,
                                    TemplateParameterList *Params,
-                                   NamedDecl *Decl,
-                                   Expr *AssociatedConstraints = nullptr);
+                                   NamedDecl *Decl);
 
   /// Create an empty class template node.
   static ClassTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID);
@@ -2862,7 +2804,21 @@ public:
     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
   /// instantiated.
   ///
@@ -3091,11 +3047,9 @@ class ConceptDecl : public TemplateDecl,
 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,

Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=374938&r1=374937&r2=374938&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Tue Oct 15 11:44:06 2019
@@ -1633,9 +1633,11 @@ template <typename Derived>
 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;

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=374938&r1=374937&r2=374938&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Oct 15 11:44:06 2019
@@ -2543,8 +2543,8 @@ def err_non_constant_constraint_expressi
 def err_non_bool_atomic_constraint : Error<
   "atomic constraint must be of type 'bool' (found %0)">;
 
-def err_template_different_associated_constraints : Error<
-  "associated constraints differ in template redeclaration">;
+def err_template_different_requires_clause : Error<
+  "requires clause differs in template redeclaration">;
 
 // C++11 char16_t/char32_t
 def warn_cxx98_compat_unicode_type : Warning<

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=374938&r1=374937&r2=374938&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Tue Oct 15 11:44:06 2019
@@ -6058,7 +6058,13 @@ public:
                                        Expr *ConstraintExpr,
                                        bool &IsSatisfied);
 
-    // ParseObjCStringLiteral - Parse Objective-C string literals.
+  /// 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.
   ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
                                     ArrayRef<Expr *> Strings);
 

Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=374938&r1=374937&r2=374938&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Tue Oct 15 11:44:06 2019
@@ -738,7 +738,7 @@ ASTContext::getCanonicalTemplateTemplate
                                            cast<TemplateTemplateParmDecl>(*P)));
   }
 
-  assert(!TTP->getRequiresClause() &&
+  assert(!TTP->getTemplateParameters()->getRequiresClause() &&
          "Unexpected requires-clause on template template-parameter");
   Expr *const CanonRequiresClause = nullptr;
 

Modified: cfe/trunk/lib/AST/DeclTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclTemplate.cpp?rev=374938&r1=374937&r2=374938&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclTemplate.cpp (original)
+++ cfe/trunk/lib/AST/DeclTemplate.cpp Tue Oct 15 11:44:06 2019
@@ -70,6 +70,8 @@ TemplateParameterList::TemplateParameter
   }
   if (RequiresClause) {
     *getTrailingObjects<Expr *>() = RequiresClause;
+    if (RequiresClause->containsUnexpandedParameterPack())
+      ContainsUnexpandedParameterPack = true;
   }
 }
 
@@ -136,6 +138,18 @@ static void AdoptTemplateParameterList(T
   }
 }
 
+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 {
 
 void *allocateDefaultArgStorageChain(const ASTContext &C) {
@@ -145,6 +159,28 @@ void *allocateDefaultArgStorageChain(con
 } // 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
 //===----------------------------------------------------------------------===//
 
@@ -344,19 +380,10 @@ ClassTemplateDecl *ClassTemplateDecl::Cr
                                              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);
-  }
-
-  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;
+  return new (C, DC) ClassTemplateDecl(C, DC, L, Name, Params, Decl);
 }
 
 ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C,
@@ -708,12 +735,6 @@ FunctionTemplateSpecializationInfo *Func
 }
 
 //===----------------------------------------------------------------------===//
-// TemplateDecl Implementation
-//===----------------------------------------------------------------------===//
-
-void TemplateDecl::anchor() {}
-
-//===----------------------------------------------------------------------===//
 // ClassTemplateSpecializationDecl Implementation
 //===----------------------------------------------------------------------===//
 

Modified: cfe/trunk/lib/Sema/SemaConcept.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaConcept.cpp?rev=374938&r1=374937&r2=374938&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaConcept.cpp (original)
+++ cfe/trunk/lib/Sema/SemaConcept.cpp Tue Oct 15 11:44:06 2019
@@ -122,4 +122,4 @@ Sema::CalculateConstraintSatisfaction(Co
   IsSatisfied = EvalResult.Val.getInt().getBoolValue();
 
   return false;
-}
+}
\ No newline at end of file

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=374938&r1=374937&r2=374938&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Oct 15 11:44:06 2019
@@ -45,27 +45,7 @@ clang::getTemplateParamsRange(TemplatePa
   return SourceRange(Ps[0]->getTemplateLoc(), Ps[N-1]->getRAngleLoc());
 }
 
-namespace clang {
-/// [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
+/// \brief Determine whether the declaration found is acceptable as the name
 /// of a template and, if so, return that template declaration. Otherwise,
 /// 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) {
     // Ensure that the template parameter lists are compatible. Skip this check
     // for a friend in a dependent context: the template parameter list itself
@@ -1547,30 +1524,6 @@ DeclResult Sema::CheckClassTemplate(
                                         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->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:
     //   In a redeclaration, partial specialization, explicit
     //   specialization or explicit instantiation of a class template,
@@ -1674,15 +1627,10 @@ DeclResult Sema::CheckClassTemplate(
     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);
@@ -7266,6 +7214,9 @@ static bool MatchTemplateParameterKind(S
                                             TemplateArgLoc);
   }
 
+  // TODO: Concepts: Match immediately-introduced-constraint for type
+  // constraints
+
   return true;
 }
 
@@ -7291,6 +7242,15 @@ void DiagnoseTemplateParameterListArityM
     << 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
 /// equivalent.
 ///
@@ -7380,6 +7340,27 @@ Sema::TemplateParameterListsAreEqual(Tem
     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;
 }
 
@@ -8089,10 +8070,9 @@ Decl *Sema::ActOnConceptDefinition(Scope
                                              TemplateParameterLists.front(),
                                              ConstraintExpr);
                                              
-  if (NewDecl->getAssociatedConstraints()) {
+  if (NewDecl->hasAssociatedConstraints()) {
     // C++2a [temp.concept]p4:
     // 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);
     NewDecl->setInvalidDecl();
   }

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=374938&r1=374937&r2=374938&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Tue Oct 15 11:44:06 2019
@@ -3515,14 +3515,21 @@ TemplateDeclInstantiator::SubstTemplateP
   if (Invalid)
     return nullptr;
 
-  // Note: we substitute into associated constraints later
-  Expr *const UninstantiatedRequiresClause = L->getRequiresClause();
+  // FIXME: Concepts: Substitution into requires clause should only happen when
+  // 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::Create(SemaRef.Context, L->getTemplateLoc(),
                                     L->getLAngleLoc(), Params,
-                                    L->getRAngleLoc(),
-                                    UninstantiatedRequiresClause);
+                                    L->getRAngleLoc(), InstRequiresClause);
   return InstL;
 }
 

Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=374938&r1=374937&r2=374938&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Tue Oct 15 11:44:06 2019
@@ -9345,9 +9345,11 @@ ASTReader::ReadTemplateParameterList(Mod
   while (NumParams--)
     Params.push_back(ReadDeclAs<NamedDecl>(F, Record, Idx));
 
-  // TODO: Concepts
+  bool HasRequiresClause = Record[Idx++];
+  Expr *RequiresClause = HasRequiresClause ? ReadExpr(F) : nullptr;
+
   TemplateParameterList *TemplateParams = TemplateParameterList::Create(
-      getContext(), TemplateLoc, LAngleLoc, Params, RAngleLoc, nullptr);
+      getContext(), TemplateLoc, LAngleLoc, Params, RAngleLoc, RequiresClause);
   return TemplateParams;
 }
 

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=374938&r1=374937&r2=374938&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Tue Oct 15 11:44:06 2019
@@ -2000,7 +2000,6 @@ DeclID ASTDeclReader::VisitTemplateDecl(
   DeclID PatternID = ReadDeclID();
   auto *TemplatedDecl = cast_or_null<NamedDecl>(Reader.GetDecl(PatternID));
   TemplateParameterList *TemplateParams = Record.readTemplateParameterList();
-  // FIXME handle associated constraints
   D->init(TemplatedDecl, TemplateParams);
 
   return PatternID;
@@ -2166,7 +2165,8 @@ void ASTDeclReader::VisitClassTemplatePa
                                     ClassTemplatePartialSpecializationDecl *D) {
   RedeclarableResult Redecl = VisitClassTemplateSpecializationDeclImpl(D);
 
-  D->TemplateParams = Record.readTemplateParameterList();
+  TemplateParameterList *Params = Record.readTemplateParameterList();
+  D->TemplateParams = Params;
   D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo();
 
   // These are read/set from/to the first declaration.
@@ -2268,7 +2268,8 @@ void ASTDeclReader::VisitVarTemplatePart
     VarTemplatePartialSpecializationDecl *D) {
   RedeclarableResult Redecl = VisitVarTemplateSpecializationDeclImpl(D);
 
-  D->TemplateParams = Record.readTemplateParameterList();
+  TemplateParameterList *Params = Record.readTemplateParameterList();
+  D->TemplateParams = Params;
   D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo();
 
   // These are read/set from/to the first declaration.
@@ -2284,6 +2285,7 @@ void ASTDeclReader::VisitTemplateTypePar
 
   D->setDeclaredWithTypename(Record.readInt());
 
+  // TODO: Concepts: Immediately introduced constraint
   if (Record.readInt())
     D->setDefaultArgument(GetTypeSourceInfo());
 }

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=374938&r1=374937&r2=374938&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Tue Oct 15 11:44:06 2019
@@ -6070,10 +6070,16 @@ void ASTRecordWriter::AddTemplateParamet
   AddSourceLocation(TemplateParams->getTemplateLoc());
   AddSourceLocation(TemplateParams->getLAngleLoc());
   AddSourceLocation(TemplateParams->getRAngleLoc());
-  // TODO: Concepts
+
   Record->push_back(TemplateParams->size());
   for (const auto &P : *TemplateParams)
     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.

Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=374938&r1=374937&r2=374938&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Tue Oct 15 11:44:06 2019
@@ -1608,7 +1608,7 @@ void ASTDeclWriter::VisitTemplateTypePar
   VisitTypeDecl(D);
 
   Record.push_back(D->wasDeclaredWithTypename());
-
+  // TODO: Concepts - constrained parameters.
   bool OwnsDefaultArg = D->hasDefaultArgument() &&
                         !D->defaultArgumentWasInherited();
   Record.push_back(OwnsDefaultArg);
@@ -1638,6 +1638,7 @@ void ASTDeclWriter::VisitNonTypeTemplate
 
     Code = serialization::DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK;
   } else {
+    // TODO: Concepts - constrained parameters.
     // Rest of NonTypeTemplateParmDecl.
     Record.push_back(D->isParameterPack());
     bool OwnsDefaultArg = D->hasDefaultArgument() &&
@@ -1667,6 +1668,7 @@ void ASTDeclWriter::VisitTemplateTemplat
       Record.AddTemplateParameterList(D->getExpansionTemplateParameters(I));
     Code = serialization::DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK;
   } else {
+    // TODO: Concepts - constrained parameters.
     // Rest of TemplateTemplateParmDecl.
     Record.push_back(D->isParameterPack());
     bool OwnsDefaultArg = D->hasDefaultArgument() &&

Added: cfe/trunk/test/CXX/temp/concept/p4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/concept/p4.cpp?rev=374938&view=auto
==============================================================================
--- cfe/trunk/test/CXX/temp/concept/p4.cpp (added)
+++ cfe/trunk/test/CXX/temp/concept/p4.cpp Tue Oct 15 11:44:06 2019
@@ -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.

Modified: cfe/trunk/test/CXX/temp/temp.constr/temp.constr.decl/class-template-decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.constr/temp.constr.decl/class-template-decl.cpp?rev=374938&r1=374937&r2=374938&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.constr/temp.constr.decl/class-template-decl.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.constr/temp.constr.decl/class-template-decl.cpp Tue Oct 15 11:44:06 2019
@@ -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 {
 
@@ -13,15 +13,15 @@ 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}}
+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> 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;
 
 template <typename T> requires true // expected-note{{previous template declaration is here}}
 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;
 
 } // end namespace diag
@@ -33,7 +33,7 @@ struct AA {
   struct A;
 };
 
-template <typename T> requires someFunc(T())
+template <typename U> requires someFunc(U())
 struct AA::A { };
 
 struct AAF {
@@ -47,18 +47,26 @@ namespace diag {
 
 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 <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>
 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;
 };
 

Added: cfe/trunk/test/CXX/temp/temp.constr/temp.constr.decl/func-template-decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.constr/temp.constr.decl/func-template-decl.cpp?rev=374938&view=auto
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.constr/temp.constr.decl/func-template-decl.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.constr/temp.constr.decl/func-template-decl.cpp Tue Oct 15 11:44:06 2019
@@ -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 at -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 at -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 at -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 at -1{{out-of-line definition of 'A' does not match any declaration in 'TA<N>'}}
+
+} // end namespace diag

Added: cfe/trunk/test/CXX/temp/temp.constr/temp.constr.decl/var-template-decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.constr/temp.constr.decl/var-template-decl.cpp?rev=374938&view=auto
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.constr/temp.constr.decl/var-template-decl.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.constr/temp.constr.decl/var-template-decl.cpp Tue Oct 15 11:44:06 2019
@@ -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
\ No newline at end of file




More information about the cfe-commits mailing list