nwilson updated this revision to Diff 46588.
nwilson added a comment.

- Fix a couple of comments to reflect the Patch.
- Clang-format the changes in this Patch.


http://reviews.llvm.org/D13357

Files:
  include/clang/AST/DeclTemplate.h
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaTemplate.cpp
  test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p1.cpp

Index: test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p1.cpp
===================================================================
--- test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p1.cpp
+++ test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p1.cpp
@@ -41,3 +41,20 @@
 void fpc(concept int i) {} // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
 
 concept bool; // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
+
+template <typename T> concept bool VCEI{ true };
+template concept bool VCEI<int>; // expected-error {{'concept' cannot be applied on an explicit instantiation}}
+extern template concept bool VCEI<int>; // expected-error {{'concept' cannot be applied on an explicit instantiation}}
+
+template <typename T> concept bool VCPS{ true };
+template <typename T> concept bool VCPS<T *>{ true }; // expected-error {{'concept' cannot be applied on an partial specialization}}
+
+template <typename T> concept bool VCES{ true };
+template <> concept bool VCES<int>{ true }; // expected-error {{'concept' cannot be applied on an explicit specialization}}
+
+template <typename T> concept bool FCEI() { return true; }
+template concept bool FCEI<int>(); // expected-error {{'concept' cannot be applied on an explicit instantiation}}
+extern template concept bool FCEI<int>(); // expected-error {{'concept' cannot be applied on an explicit instantiation}}
+
+template <typename T> concept bool FCES() { return true; }
+template <> concept bool FCES<bool>() { return true; } // expected-error {{'concept' cannot be applied on an explicit specialization}}
Index: lib/Sema/SemaTemplate.cpp
===================================================================
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -7673,6 +7673,15 @@
     Diag(D.getDeclSpec().getConstexprSpecLoc(),
          diag::err_explicit_instantiation_constexpr);
 
+  // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be
+  // applied only to the definition of a function template or variable template,
+  // declared in namespace scope.
+  if (D.getDeclSpec().isConceptSpecified()) {
+    Diag(D.getDeclSpec().getConceptSpecLoc(),
+         diag::err_concept_specified_specialization) << 0;
+    return true;
+  }
+
   // C++0x [temp.explicit]p2:
   //   There are two forms of explicit instantiation: an explicit instantiation
   //   definition and an explicit instantiation declaration. An explicit
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -6002,6 +6002,16 @@
         NewVD->setInvalidDecl(true);
       }
 
+      // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be
+      // applied only to the definition of a [...] variable template, declared
+      // in namespace scope. [...] A concept definition refers to [...] a
+      // variable concept and its initializer.
+      if (IsVariableTemplateSpecialization) {
+        Diag(D.getDeclSpec().getConceptSpecLoc(),
+             diag::err_concept_specified_specialization)
+            << (IsPartialSpecialization ? 2 : 1);
+      }
+
       // C++ Concepts TS [dcl.spec.concept]p6: A variable concept has the
       // following restrictions:
       // - The declared type shall have the type bool.
@@ -7667,6 +7677,10 @@
     }
 
     if (isConcept) {
+      // This is a function concept.
+      if (FunctionTemplateDecl *FTD = NewFD->getDescribedFunctionTemplate())
+        FTD->setConcept(true);
+
       // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be
       // applied only to the definition of a function template [...]
       if (!D.isFunctionDefinition()) {
@@ -7733,6 +7747,15 @@
             << 1 << 3;
         NewFD->setInvalidDecl(true);
       }
+
+      // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be
+      // applied only to the definition of a function template [...], declared
+      // in namespace scope. [...] A concept definition refers to either a
+      // function concept and its definition [...].
+      if (isFunctionTemplateSpecialization) {
+        Diag(D.getDeclSpec().getConceptSpecLoc(),
+             diag::err_concept_specified_specialization) << 1;
+      }
     }
 
     // If __module_private__ was specified, mark the function accordingly.
@@ -7994,9 +8017,9 @@
                                          TemplateId->NumArgs);
       translateTemplateArguments(TemplateArgsPtr,
                                  TemplateArgs);
-    
+
       HasExplicitTemplateArgs = true;
-    
+
       if (NewFD->isInvalidDecl()) {
         HasExplicitTemplateArgs = false;
       } else if (FunctionTemplate) {
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -2080,6 +2080,9 @@
   "declared return type of function concept must be 'bool'">;
 def err_variable_concept_bool_decl : Error<
   "declared type of variable concept must be 'bool'">;
+def err_concept_specified_specialization : Error<
+  "'concept' cannot be applied on an "
+  "%select{explicit instantiation|explicit specialization|partial specialization}0">;
 
 // C++11 char16_t/char32_t
 def warn_cxx98_compat_unicode_type : Warning<
Index: include/clang/AST/DeclTemplate.h
===================================================================
--- include/clang/AST/DeclTemplate.h
+++ include/clang/AST/DeclTemplate.h
@@ -332,32 +332,31 @@
   void anchor() override;
 protected:
   // This is probably never used.
-  TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
-               DeclarationName Name)
-    : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr),
-      TemplateParams(nullptr) {}
+  TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name)
+      : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr, false),
+        TemplateParams(nullptr) {}
 
   // Construct a template decl with the given name and parameters.
   // Used when there is not templated element (tt-params).
-  TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
-               DeclarationName Name, TemplateParameterList *Params)
-    : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr),
-      TemplateParams(Params) {}
+  TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name,
+               TemplateParameterList *Params)
+      : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr, false),
+        TemplateParams(Params) {}
 
   // Construct a template decl with name, parameters, and templated element.
-  TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
-               DeclarationName Name, TemplateParameterList *Params,
-               NamedDecl *Decl)
-    : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl),
-      TemplateParams(Params) { }
+  TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name,
+               TemplateParameterList *Params, NamedDecl *Decl)
+      : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl, false),
+        TemplateParams(Params) {}
+
 public:
   /// Get the list of template parameters
   TemplateParameterList *getTemplateParameters() const {
     return TemplateParams;
   }
 
   /// Get the underlying, templated declaration.
-  NamedDecl *getTemplatedDecl() const { return TemplatedDecl; }
+  NamedDecl *getTemplatedDecl() const { return TemplatedDecl.getPointer(); }
 
   // Implement isa/cast/dyncast/etc.
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -367,20 +366,30 @@
 
   SourceRange getSourceRange() const override LLVM_READONLY {
     return SourceRange(TemplateParams->getTemplateLoc(),
-                       TemplatedDecl->getSourceRange().getEnd());
+                       TemplatedDecl.getPointer()->getSourceRange().getEnd());
   }
 
+  /// Whether this is a (C++ Concepts TS) function or variable concept.
+  bool isConcept() const { return TemplatedDecl.getInt(); }
+  void setConcept(bool IC) { TemplatedDecl.setInt(true); }
+
 protected:
-  NamedDecl *TemplatedDecl;
+  /// \brief The named declaration from which this template was instantiated.
+  /// (or null).
+  ///
+  /// The boolean value will be true to indicate that this template
+  /// (function or variable) is a concept.
+  llvm::PointerIntPair<NamedDecl *, 1, bool> TemplatedDecl;
+
   TemplateParameterList* TemplateParams;
 
 public:
   /// \brief Initialize the underlying templated declaration and
   /// template parameters.
   void init(NamedDecl *templatedDecl, TemplateParameterList* templateParams) {
-    assert(!TemplatedDecl && "TemplatedDecl already set!");
+    assert(!TemplatedDecl.getPointer() && "TemplatedDecl already set!");
     assert(!TemplateParams && "TemplateParams already set!");
-    TemplatedDecl = templatedDecl;
+    TemplatedDecl.setPointer(templatedDecl);
     TemplateParams = templateParams;
   }
 };
@@ -889,7 +898,7 @@
 
   /// Get the underlying function declaration of the template.
   FunctionDecl *getTemplatedDecl() const {
-    return static_cast<FunctionDecl*>(TemplatedDecl);
+    return static_cast<FunctionDecl *>(TemplatedDecl.getPointer());
   }
 
   /// Returns whether this template declaration defines the primary
@@ -1982,7 +1991,7 @@
 
   /// \brief Get the underlying class declarations of the template.
   CXXRecordDecl *getTemplatedDecl() const {
-    return static_cast<CXXRecordDecl *>(TemplatedDecl);
+    return static_cast<CXXRecordDecl *>(TemplatedDecl.getPointer());
   }
 
   /// \brief Returns whether this template declaration defines the primary
@@ -2245,7 +2254,7 @@
 public:
   /// Get the underlying function declaration of the template.
   TypeAliasDecl *getTemplatedDecl() const {
-    return static_cast<TypeAliasDecl*>(TemplatedDecl);
+    return static_cast<TypeAliasDecl *>(TemplatedDecl.getPointer());
   }
 
 
@@ -2808,7 +2817,7 @@
 
   /// \brief Get the underlying variable declarations of the template.
   VarDecl *getTemplatedDecl() const {
-    return static_cast<VarDecl *>(TemplatedDecl);
+    return static_cast<VarDecl *>(TemplatedDecl.getPointer());
   }
 
   /// \brief Returns whether this template declaration defines the primary
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to