nwilson updated this revision to Diff 33587. nwilson added a comment. Change the wording of diagnostic message and quote the invalid specifier. Add 'friend' as an invalid specifier and diagnose function concepts when 'friend' is specified. Reorder the list of invalid specifiers and corresponding checks in the code to match the TS.
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,13 @@ +// 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 'thread_local'}} + +template<typename T> concept constexpr bool VCC = true; // expected-error {{variable concept cannot be declared 'constexpr'}} + +template<typename T> concept inline bool FCI() { return true; } // expected-error {{function concept cannot be declared 'inline'}} + +struct X { + template<typename T> concept friend bool FCF() { return true; } // expected-error {{function concept cannot be declared 'friend'}} +}; + +template<typename T> concept constexpr bool FCC() { return true; } // expected-error {{function concept cannot be declared 'constexpr'}} 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_specifiers) + << 0 << 0; + NewVD->setInvalidDecl(true); + } + + if (D.getDeclSpec().isConstexprSpecified()) { + Diag(D.getDeclSpec().getConstexprSpecLoc(), + diag::err_concept_decl_invalid_specifiers) + << 0 << 3; + NewVD->setInvalidDecl(true); + } + } } // Set the lexical context. If the declarator has a C++ scope specifier, the @@ -7497,6 +7515,30 @@ // 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 (isInline) { + Diag(D.getDeclSpec().getInlineSpecLoc(), + diag::err_concept_decl_invalid_specifiers) + << 1 << 1; + NewFD->setInvalidDecl(true); + } + + if (isFriend) { + Diag(D.getDeclSpec().getFriendSpecLoc(), + diag::err_concept_decl_invalid_specifiers) + << 1 << 2; + NewFD->setInvalidDecl(true); + } + + if (isConstexpr) { + Diag(D.getDeclSpec().getConstexprSpecLoc(), + diag::err_concept_decl_invalid_specifiers) + << 1 << 3; + 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_specifiers : Error< + "%select{variable|function}0 concept cannot be declared " + "'%select{thread_local|inline|friend|constexpr}1'">; // 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,13 @@ +// 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 'thread_local'}} + +template<typename T> concept constexpr bool VCC = true; // expected-error {{variable concept cannot be declared 'constexpr'}} + +template<typename T> concept inline bool FCI() { return true; } // expected-error {{function concept cannot be declared 'inline'}} + +struct X { + template<typename T> concept friend bool FCF() { return true; } // expected-error {{function concept cannot be declared 'friend'}} +}; + +template<typename T> concept constexpr bool FCC() { return true; } // expected-error {{function concept cannot be declared 'constexpr'}} 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_specifiers) + << 0 << 0; + NewVD->setInvalidDecl(true); + } + + if (D.getDeclSpec().isConstexprSpecified()) { + Diag(D.getDeclSpec().getConstexprSpecLoc(), + diag::err_concept_decl_invalid_specifiers) + << 0 << 3; + NewVD->setInvalidDecl(true); + } + } } // Set the lexical context. If the declarator has a C++ scope specifier, the @@ -7497,6 +7515,30 @@ // 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 (isInline) { + Diag(D.getDeclSpec().getInlineSpecLoc(), + diag::err_concept_decl_invalid_specifiers) + << 1 << 1; + NewFD->setInvalidDecl(true); + } + + if (isFriend) { + Diag(D.getDeclSpec().getFriendSpecLoc(), + diag::err_concept_decl_invalid_specifiers) + << 1 << 2; + NewFD->setInvalidDecl(true); + } + + if (isConstexpr) { + Diag(D.getDeclSpec().getConstexprSpecLoc(), + diag::err_concept_decl_invalid_specifiers) + << 1 << 3; + 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_specifiers : Error< + "%select{variable|function}0 concept cannot be declared " + "'%select{thread_local|inline|friend|constexpr}1'">; // 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