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

Diagnose variable and function concept declarations when an invalid specifier 
appears

http://reviews.llvm.org/D12435

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/Sema/SemaDecl.cpp
  test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.concept/p2.cpp

Index: test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.concept/p2.cpp
===================================================================
--- /dev/null
+++ test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.concept/p2.cpp
@@ -0,0 +1,9 @@
+// RUN:  %clang_cc1 -std=c++14 -fconcepts-ts -x c++ -verify %s
+
+template<typename T> concept thread_local bool VCTL = true; // expected-error 
{{variable concept cannot be declared with thread_local specified}}
+
+template<typename T> concept constexpr bool VCC = true; // expected-error 
{{variable concept cannot be declared with constexpr specified}}
+
+template<typename T> concept constexpr bool FCC() { return true; } // 
expected-error {{function concept cannot be declared with constexpr specified}}
+
+template<typename T> concept inline bool FCI() { return true; } // 
expected-error {{function concept cannot be declared with inline specified}}
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -5871,8 +5871,26 @@
     if (D.getDeclSpec().isConstexprSpecified())
       NewVD->setConstexpr(true);
 
-    if (D.getDeclSpec().isConceptSpecified())
+    if (D.getDeclSpec().isConceptSpecified()) {
       NewVD->setConcept(true);
+
+      // C++ Concepts TS [dcl.spec.concept]p2: A concept definition shall not
+      // be declared with the thread_local, inline, friend, or constexpr
+      // specifiers, [...]
+      if (D.getDeclSpec().getThreadStorageClassSpec() == TSCS_thread_local) {
+        Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
+             diag::err_concept_decl_invalid_sepcifiers)
+            << 0 << 0;
+        NewVD->setInvalidDecl(true);
+      }
+
+      if (D.getDeclSpec().isConstexprSpecified()) {
+        Diag(D.getDeclSpec().getConstexprSpecLoc(),
+             diag::err_concept_decl_invalid_sepcifiers)
+            << 0 << 1;
+        NewVD->setInvalidDecl(true);
+      }
+    }
   }
 
   // Set the lexical context. If the declarator has a C++ scope specifier, the
@@ -7497,6 +7515,23 @@
       // C++ Concepts TS [dcl.spec.concept]p2: Every concept definition is
       // implicity defined to be a constexpr declaration (implicitly inline)
       NewFD->setImplicitlyInline();
+
+      // C++ Concepts TS [dcl.spec.concept]p2: A concept definition shall not
+      // be declared with the thread_local, inline, friend, or constexpr
+      // specifiers, [...]
+      if (isConstexpr) {
+        Diag(D.getDeclSpec().getConstexprSpecLoc(),
+             diag::err_concept_decl_invalid_sepcifiers)
+            << 1 << 1;
+        NewFD->setInvalidDecl(true);
+      }
+
+      if (isInline) {
+        Diag(D.getDeclSpec().getInlineSpecLoc(),
+             diag::err_concept_decl_invalid_sepcifiers)
+            << 1 << 2;
+        NewFD->setInvalidDecl(true);
+      }
     }
 
     // If __module_private__ was specified, mark the function accordingly.
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -1979,6 +1979,9 @@
   "variable concept declaration must be initialized">;
 def err_function_concept_exception_spec : Error<
   "function concept cannot have exception specification">;
+def err_concept_decl_invalid_sepcifiers : Error<
+  "%select{variable|function}0 concept cannot be declared with "
+  "%select{thread_local|constexpr|inline}1 specified">;
 
 // C++11 char16_t/char32_t
 def warn_cxx98_compat_unicode_type : Warning<


Index: test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.concept/p2.cpp
===================================================================
--- /dev/null
+++ test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.concept/p2.cpp
@@ -0,0 +1,9 @@
+// RUN:  %clang_cc1 -std=c++14 -fconcepts-ts -x c++ -verify %s
+
+template<typename T> concept thread_local bool VCTL = true; // expected-error {{variable concept cannot be declared with thread_local specified}}
+
+template<typename T> concept constexpr bool VCC = true; // expected-error {{variable concept cannot be declared with constexpr specified}}
+
+template<typename T> concept constexpr bool FCC() { return true; } // expected-error {{function concept cannot be declared with constexpr specified}}
+
+template<typename T> concept inline bool FCI() { return true; } // expected-error {{function concept cannot be declared with inline specified}}
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -5871,8 +5871,26 @@
     if (D.getDeclSpec().isConstexprSpecified())
       NewVD->setConstexpr(true);
 
-    if (D.getDeclSpec().isConceptSpecified())
+    if (D.getDeclSpec().isConceptSpecified()) {
       NewVD->setConcept(true);
+
+      // C++ Concepts TS [dcl.spec.concept]p2: A concept definition shall not
+      // be declared with the thread_local, inline, friend, or constexpr
+      // specifiers, [...]
+      if (D.getDeclSpec().getThreadStorageClassSpec() == TSCS_thread_local) {
+        Diag(D.getDeclSpec().getThreadStorageClassSpecLoc(),
+             diag::err_concept_decl_invalid_sepcifiers)
+            << 0 << 0;
+        NewVD->setInvalidDecl(true);
+      }
+
+      if (D.getDeclSpec().isConstexprSpecified()) {
+        Diag(D.getDeclSpec().getConstexprSpecLoc(),
+             diag::err_concept_decl_invalid_sepcifiers)
+            << 0 << 1;
+        NewVD->setInvalidDecl(true);
+      }
+    }
   }
 
   // Set the lexical context. If the declarator has a C++ scope specifier, the
@@ -7497,6 +7515,23 @@
       // C++ Concepts TS [dcl.spec.concept]p2: Every concept definition is
       // implicity defined to be a constexpr declaration (implicitly inline)
       NewFD->setImplicitlyInline();
+
+      // C++ Concepts TS [dcl.spec.concept]p2: A concept definition shall not
+      // be declared with the thread_local, inline, friend, or constexpr
+      // specifiers, [...]
+      if (isConstexpr) {
+        Diag(D.getDeclSpec().getConstexprSpecLoc(),
+             diag::err_concept_decl_invalid_sepcifiers)
+            << 1 << 1;
+        NewFD->setInvalidDecl(true);
+      }
+
+      if (isInline) {
+        Diag(D.getDeclSpec().getInlineSpecLoc(),
+             diag::err_concept_decl_invalid_sepcifiers)
+            << 1 << 2;
+        NewFD->setInvalidDecl(true);
+      }
     }
 
     // If __module_private__ was specified, mark the function accordingly.
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -1979,6 +1979,9 @@
   "variable concept declaration must be initialized">;
 def err_function_concept_exception_spec : Error<
   "function concept cannot have exception specification">;
+def err_concept_decl_invalid_sepcifiers : Error<
+  "%select{variable|function}0 concept cannot be declared with "
+  "%select{thread_local|constexpr|inline}1 specified">;
 
 // C++11 char16_t/char32_t
 def warn_cxx98_compat_unicode_type : Warning<
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to