From 085b9ff6e257bb961f2f2edbb62a5e33c8a2cc3a Mon Sep 17 00:00:00 2001 From: Nathan Wilson Date: Wed, 9 Sep 2015 21:48:31 +0000 Subject: [PATCH] [Concepts] Add diagnostic; invalid specifier on function or variable concept declaration Summary: Diagnose variable and function concept declarations when an invalid specifier appears Reviewers: rsmith, aaron.ballman, faisalv, fraggamuffin, hubert.reinterpretcast Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D12435 llvm-svn: 247194 --- .../clang/Basic/DiagnosticSemaKinds.td | 3 ++ clang/lib/Sema/SemaDecl.cpp | 44 ++++++++++++++++++- .../dcl.dcl/dcl.spec/dcl.concept/p2.cpp | 13 ++++++ 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 clang/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.concept/p2.cpp diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 2c3b22a21bf4..2fa7f01d0801 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1980,6 +1980,9 @@ def err_var_concept_not_initialized : Error< "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< diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index acff354f70e8..c55c07efb770 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -5876,8 +5876,26 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, 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 @@ -7502,6 +7520,30 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // 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. diff --git a/clang/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.concept/p2.cpp b/clang/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.concept/p2.cpp new file mode 100644 index 000000000000..477910986de1 --- /dev/null +++ b/clang/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 concept thread_local bool VCTL = true; // expected-error {{variable concept cannot be declared 'thread_local'}} + +template concept constexpr bool VCC = true; // expected-error {{variable concept cannot be declared 'constexpr'}} + +template concept inline bool FCI() { return true; } // expected-error {{function concept cannot be declared 'inline'}} + +struct X { + template concept friend bool FCF() { return true; } // expected-error {{function concept cannot be declared 'friend'}} +}; + +template concept constexpr bool FCC() { return true; } // expected-error {{function concept cannot be declared 'constexpr'}}