nwilson created this revision.
nwilson added reviewers: rsmith, hubert.reinterpretcast, aaron.ballman, 
faisalv, fraggamuffin.
nwilson added a subscriber: cfe-commits.

http://reviews.llvm.org/D13357

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

Index: test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.concept/p7.cpp
===================================================================
--- /dev/null
+++ test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.concept/p7.cpp
@@ -0,0 +1,16 @@
+// RUN:  %clang_cc1 -std=c++14 -fconcepts-ts -x c++ -verify %s
+
+template<typename T> concept bool VCEI { true };
+template concept bool VCEI<int>; // expected-error {{variable concept cannot be explicitly instantiated}}
+
+template<typename T> concept bool VCPS { true };
+template<typename T> concept bool VCPS<T*> { true }; // expected-error {{variable concept cannot be partially specialized}}
+
+template<typename T> concept bool VCES { true };
+template<> concept bool VCES<int> { true }; // expected-error {{variable concept cannot be explicitly specialized}}
+
+template<typename T> concept bool FCEI() { return true; }
+template concept bool FCEI<int>(); // expected-error {{function concept cannot be explicitly instantiated}}
+
+template<typename T> concept bool FCES() { return true; }
+template<> concept bool FCES<bool>() { return true; } // expected-error {{function concept cannot be explicitly specialized}}
Index: lib/Sema/SemaTemplate.cpp
===================================================================
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -7588,6 +7588,14 @@
     Diag(D.getDeclSpec().getConstexprSpecLoc(),
          diag::err_explicit_instantiation_constexpr);
 
+  // C++ Concepts TS [dcl.spec.concept]p7: A program shall not declare an
+  // explicit instantiation, [...] of a concept definition.
+  if (D.getDeclSpec().isConceptSpecified() && R->isFunctionType()) {
+    Diag(D.getIdentifierLoc(), diag::err_concept_decl_specialized)
+      << 1 << 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
@@ -7659,6 +7667,14 @@
         return true;
       }
 
+      // C++ Concepts TS [dcl.spec.concept]p7: A program shall not declare an
+      // explicit instantiation, [...] of a concept definition.
+      if (D.getDeclSpec().isConceptSpecified()) {
+        Diag(D.getIdentifierLoc(), diag::err_concept_decl_specialized)
+          << 0 << 0;
+        return true;
+      }
+
       // Translate the parser's template argument list into our AST format.
       TemplateArgumentListInfo TemplateArgs =
           makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -5898,6 +5898,21 @@
             << 0 << 3;
         NewVD->setInvalidDecl(true);
       }
+
+      // C++ Concepts TS [dcl.spec.concept]p7: A program shall not declare [...]
+      //  an explicit specialization, or a partial specialization of a concept
+      // definition
+      if (IsVariableTemplateSpecialization && !IsPartialSpecialization) {
+        Diag(NewVD->getLocation(), diag::err_concept_decl_specialized)
+          << 0 << 1;
+        NewVD->setInvalidDecl(true);
+      }
+
+      if (IsVariableTemplateSpecialization && IsPartialSpecialization) {
+        Diag(NewVD->getLocation(), diag::err_concept_decl_specialized)
+          << 0 << 2;
+        NewVD->setInvalidDecl(true);
+      }
     }
   }
 
@@ -7544,6 +7559,9 @@
     }
 
     if (isConcept) {
+      // This is a function concept
+      NewFD->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()) {
@@ -7595,6 +7613,14 @@
             << 1 << 3;
         NewFD->setInvalidDecl(true);
       }
+
+      // C++ Concepts TS [dcl.spec.concept]p7: A program shall not declare [...]
+      // an explicit specialization, [...] of a concept definition.
+      if (isFunctionTemplateSpecialization) {
+        Diag(NewFD->getLocation(), diag::err_concept_decl_specialized)
+          << 1 << 1;
+        NewFD->setInvalidDecl();
+      }
     }
 
     // If __module_private__ was specified, mark the function accordingly.
@@ -7858,8 +7884,8 @@
                                  TemplateArgs);
     
       HasExplicitTemplateArgs = true;
-    
-      if (NewFD->isInvalidDecl()) {
+
+      if (NewFD->isInvalidDecl() && !NewFD->isConcept()) {
         HasExplicitTemplateArgs = false;
       } else if (FunctionTemplate) {
         // Function template with explicit template arguments.
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -1986,6 +1986,9 @@
 def err_concept_decl_invalid_specifiers : Error<
   "%select{variable|function}0 concept cannot be declared "
   "'%select{thread_local|inline|friend|constexpr}1'">;
+def err_concept_decl_specialized : Error<
+  "%select{variable|function}0 concept cannot be "
+  "%select{explicitly instantiated|explicitly specialized|partially specialized}1">;
 
 // C++11 char16_t/char32_t
 def warn_cxx98_compat_unicode_type : Warning<
Index: include/clang/AST/Decl.h
===================================================================
--- include/clang/AST/Decl.h
+++ include/clang/AST/Decl.h
@@ -1574,6 +1574,7 @@
   bool HasImplicitReturnZero : 1;
   bool IsLateTemplateParsed : 1;
   bool IsConstexpr : 1;
+  bool IsConcept : 1;
 
   /// \brief Indicates if the function uses __try.
   bool UsesSEHTry : 1;
@@ -1847,6 +1848,10 @@
   bool isConstexpr() const { return IsConstexpr; }
   void setConstexpr(bool IC) { IsConstexpr = IC; }
 
+  /// Whether this is a (C++ Concepts TS) function concept.
+  bool isConcept() const { return IsConcept; }
+  void setConcept(bool IC) { IsConcept = IC; }
+
   /// \brief Indicates the function uses __try.
   bool usesSEHTry() const { return UsesSEHTry; }
   void setUsesSEHTry(bool UST) { UsesSEHTry = UST; }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to