summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Wilson <nwilson20@gmail.com>2016-04-09 02:55:27 +0000
committerNathan Wilson <nwilson20@gmail.com>2016-04-09 02:55:27 +0000
commit8383912f8700297a7cc6d5be7e8bbaed71057067 (patch)
treedee01919075e220cfee03acbf6657ae59093bdce
parentdd77e1e6a53cbf807783492706bcfa7a5d849148 (diff)
downloadbcm5719-llvm-8383912f8700297a7cc6d5be7e8bbaed71057067.tar.gz
bcm5719-llvm-8383912f8700297a7cc6d5be7e8bbaed71057067.zip
[Concepts] Implement subsection [dcl.spec.concept]p7 of the Concepts TS
Summary: A program shall not declare an explicit instantiation (14.8.2), an explicit specialization (14.8.3), or a partial specialization of a concept definition. Reviewers: rsmith, hubert.reinterpretcast, faisalv, aaron.ballman Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D18221 llvm-svn: 265868
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td3
-rw-r--r--clang/lib/Sema/SemaDecl.cpp21
-rw-r--r--clang/lib/Sema/SemaTemplate.cpp28
-rw-r--r--clang/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p7.cpp18
4 files changed, 70 insertions, 0 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 6f4c863a0a6..cc385bff72e 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2098,6 +2098,9 @@ def err_variable_concept_bool_decl : Error<
def err_concept_specified_specialization : Error<
"'concept' cannot be applied on an "
"%select{explicit instantiation|explicit specialization|partial specialization}0">;
+def err_concept_specialized : Error<
+ "%select{function|variable}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<
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 774af59e497..35682943907 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -6285,6 +6285,25 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (!IsVariableTemplateSpecialization)
D.setRedeclaration(CheckVariableDeclaration(NewVD, Previous));
+ // C++ Concepts TS [dcl.spec.concept]p7: A program shall not declare [...]
+ // an explicit specialization (14.8.3) or a partial specialization of a
+ // concept definition.
+ if (IsVariableTemplateSpecialization &&
+ !D.getDeclSpec().isConceptSpecified() && !Previous.empty() &&
+ Previous.isSingleResult()) {
+ NamedDecl *PreviousDecl = Previous.getFoundDecl();
+ if (VarTemplateDecl *VarTmpl = dyn_cast<VarTemplateDecl>(PreviousDecl)) {
+ if (VarTmpl->isConcept()) {
+ Diag(NewVD->getLocation(), diag::err_concept_specialized)
+ << 1 /*variable*/
+ << (IsPartialSpecialization ? 2 /*partially specialized*/
+ : 1 /*explicitly specialized*/);
+ Diag(VarTmpl->getLocation(), diag::note_previous_declaration);
+ NewVD->setInvalidDecl();
+ }
+ }
+ }
+
if (NewTemplate) {
VarTemplateDecl *PrevVarTemplate =
NewVD->getPreviousDecl()
@@ -7823,6 +7842,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (isFunctionTemplateSpecialization) {
Diag(D.getDeclSpec().getConceptSpecLoc(),
diag::err_concept_specified_specialization) << 1;
+ NewFD->setInvalidDecl(true);
+ return NewFD;
}
}
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index fdb7d762d29..d840e426d7a 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -6920,6 +6920,15 @@ bool Sema::CheckFunctionTemplateSpecialization(
// Ignore access information; it doesn't figure into redeclaration checking.
FunctionDecl *Specialization = cast<FunctionDecl>(*Result);
+ // C++ Concepts TS [dcl.spec.concept]p7: A program shall not declare [...]
+ // an explicit specialization (14.8.3) [...] of a concept definition.
+ if (Specialization->getPrimaryTemplate()->isConcept()) {
+ Diag(FD->getLocation(), diag::err_concept_specialized)
+ << 0 /*function*/ << 1 /*explicitly specialized*/;
+ Diag(Specialization->getLocation(), diag::note_previous_declaration);
+ return true;
+ }
+
FunctionTemplateSpecializationInfo *SpecInfo
= Specialization->getTemplateSpecializationInfo();
assert(SpecInfo && "Function template specialization info missing?");
@@ -7774,6 +7783,15 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
return true;
}
+ // C++ Concepts TS [dcl.spec.concept]p7: A program shall not declare an
+ // explicit instantiation (14.8.2) [...] of a concept definition.
+ if (PrevTemplate->isConcept()) {
+ Diag(D.getIdentifierLoc(), diag::err_concept_specialized)
+ << 1 /*variable*/ << 0 /*explicitly instantiated*/;
+ Diag(PrevTemplate->getLocation(), diag::note_previous_declaration);
+ return true;
+ }
+
// Translate the parser's template argument list into our AST format.
TemplateArgumentListInfo TemplateArgs =
makeTemplateArgumentListInfo(*this, *D.getName().TemplateId);
@@ -7988,6 +8006,16 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
diag::ext_explicit_instantiation_without_qualified_id)
<< Specialization << D.getCXXScopeSpec().getRange();
+ // C++ Concepts TS [dcl.spec.concept]p7: A program shall not declare an
+ // explicit instantiation (14.8.2) [...] of a concept definition.
+ if (FunTmpl && FunTmpl->isConcept() &&
+ !D.getDeclSpec().isConceptSpecified()) {
+ Diag(D.getIdentifierLoc(), diag::err_concept_specialized)
+ << 0 /*function*/ << 0 /*explicitly instantiated*/;
+ Diag(FunTmpl->getLocation(), diag::note_previous_declaration);
+ return true;
+ }
+
CheckExplicitInstantiationScope(*this,
FunTmpl? (NamedDecl *)FunTmpl
: Specialization->getInstantiatedFromMemberFunction(),
diff --git a/clang/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p7.cpp b/clang/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p7.cpp
new file mode 100644
index 00000000000..1bad6bb9329
--- /dev/null
+++ b/clang/test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p7.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -std=c++14 -fconcepts-ts -x c++ -verify %s
+
+template <typename T> concept bool FCEI() { return true; } // expected-note {{previous declaration is here}} expected-note {{previous declaration is here}}
+template bool FCEI<int>(); // expected-error {{function concept cannot be explicitly instantiated}}
+extern template bool FCEI<double>(); // expected-error {{function concept cannot be explicitly instantiated}}
+
+template <typename T> concept bool FCES() { return true; } // expected-note {{previous declaration is here}}
+template <> bool FCES<int>() { return true; } // expected-error {{function concept cannot be explicitly specialized}}
+
+template <typename T> concept bool VC { true }; // expected-note {{previous declaration is here}} expected-note {{previous declaration is here}}
+template bool VC<int>; // expected-error {{variable concept cannot be explicitly instantiated}}
+extern template bool VC<double>; // expected-error {{variable concept cannot be explicitly instantiated}}
+
+template <typename T> concept bool VCES { true }; // expected-note {{previous declaration is here}}
+template <> bool VCES<int> { true }; // expected-error {{variable concept cannot be explicitly specialized}}
+
+template <typename T> concept bool VCPS { true }; // expected-note {{previous declaration is here}}
+template <typename T> bool VCPS<T *> { true }; // expected-error {{variable concept cannot be partially specialized}}
OpenPOWER on IntegriCloud