nwilson updated this revision to Diff 43670.
nwilson added a comment.
- Store the IsConcept boolean flag in TemplateDecl by making TemplatedDecl an
IntPointerPair, and move the associated member functions into TemplateDecl.
- Remove unnecessary quoted comment.
- Remove an extra space where the diagnostic is used.
http://reviews.llvm.org/D13357
Files:
include/clang/AST/DeclTemplate.h
include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDecl.cpp
lib/Sema/SemaTemplate.cpp
test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p1.cpp
Index: test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p1.cpp
===================================================================
--- test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p1.cpp
+++ test/CXX/concepts-ts/dcl.dcl/dcl.spec/dcl.spec.concept/p1.cpp
@@ -41,3 +41,20 @@
void fpc(concept int i) {} // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
concept bool; // expected-error {{'concept' can only appear on the definition of a function template or variable template}}
+
+template<typename T> concept bool VCEI { true };
+template concept bool VCEI<int>; // expected-error {{'concept' cannot be applied on an explicit instantiation}}
+extern template concept bool VCEI<int>; // expected-error {{'concept' cannot be applied on an explicit instantiation}}
+
+template<typename T> concept bool VCPS { true };
+template<typename T> concept bool VCPS<T*> { true }; // expected-error {{'concept' cannot be applied on an partial specialization}}
+
+template<typename T> concept bool VCES { true };
+template<> concept bool VCES<int> { true }; // expected-error {{'concept' cannot be applied on an explicit specialization}}
+
+template<typename T> concept bool FCEI() { return true; }
+template concept bool FCEI<int>(); // expected-error {{'concept' cannot be applied on an explicit instantiation}}
+extern template concept bool FCEI<int>(); // expected-error {{'concept' cannot be applied on an explicit instantiation}}
+
+template<typename T> concept bool FCES() { return true; }
+template<> concept bool FCES<bool>() { return true; } // expected-error {{'concept' cannot be applied on an explicit specialization}}
Index: lib/Sema/SemaTemplate.cpp
===================================================================
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -7668,6 +7668,15 @@
Diag(D.getDeclSpec().getConstexprSpecLoc(),
diag::err_explicit_instantiation_constexpr);
+ // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be
+ // applied only to the definition of a function template or variable template,
+ // declared in namespace scope.
+ if (D.getDeclSpec().isConceptSpecified()) {
+ Diag(D.getDeclSpec().getConceptSpecLoc(),
+ diag::err_concept_specified_specialization) << 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
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -5988,6 +5988,16 @@
<< 0 << 3;
NewVD->setInvalidDecl(true);
}
+
+ // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be
+ // applied only to the definition of a [...] variable template, declared
+ // in namespace scope. [...] A concept definition refers to [...] a
+ // variable concept and its initializer.
+ if (IsVariableTemplateSpecialization) {
+ Diag(D.getDeclSpec().getConceptSpecLoc(),
+ diag::err_concept_specified_specialization)
+ << (IsPartialSpecialization ? 2 : 1);
+ }
}
}
@@ -7645,6 +7655,10 @@
}
if (isConcept) {
+ // This is a function concept.
+ if (FunctionTemplateDecl *FTD = NewFD->getDescribedFunctionTemplate())
+ FTD->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()) {
@@ -7703,6 +7717,15 @@
<< 1 << 3;
NewFD->setInvalidDecl(true);
}
+
+ // C++ Concepts TS [dcl.spec.concept]p1: The concept specifier shall be
+ // applied only to the definition of a function template [...], declared
+ // in namespace scope. [...] A concept definition refers to either a
+ // function concept and its definition [...].
+ if (isFunctionTemplateSpecialization) {
+ Diag(D.getDeclSpec().getConceptSpecLoc(),
+ diag::err_concept_specified_specialization) << 1;
+ }
}
// If __module_private__ was specified, mark the function accordingly.
@@ -7964,9 +7987,9 @@
TemplateId->NumArgs);
translateTemplateArguments(TemplateArgsPtr,
TemplateArgs);
-
+
HasExplicitTemplateArgs = true;
-
+
if (NewFD->isInvalidDecl()) {
HasExplicitTemplateArgs = false;
} else if (FunctionTemplate) {
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -2068,6 +2068,9 @@
"'%select{thread_local|inline|friend|constexpr}1'">;
def err_function_concept_with_params : Error<
"function concept cannot have any parameters">;
+def err_concept_specified_specialization : Error<
+ "'concept' cannot be applied on an "
+ "%select{explicit instantiation|explicit specialization|partial specialization}0">;
// C++11 char16_t/char32_t
def warn_cxx98_compat_unicode_type : Warning<
Index: include/clang/AST/DeclTemplate.h
===================================================================
--- include/clang/AST/DeclTemplate.h
+++ include/clang/AST/DeclTemplate.h
@@ -334,30 +334,30 @@
// This is probably never used.
TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
DeclarationName Name)
- : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr),
+ : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr, false),
TemplateParams(nullptr) {}
// Construct a template decl with the given name and parameters.
// Used when there is not templated element (tt-params).
TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
DeclarationName Name, TemplateParameterList *Params)
- : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr),
+ : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr, false),
TemplateParams(Params) {}
// Construct a template decl with name, parameters, and templated element.
TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
DeclarationName Name, TemplateParameterList *Params,
NamedDecl *Decl)
- : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl),
+ : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl, false),
TemplateParams(Params) { }
public:
/// Get the list of template parameters
TemplateParameterList *getTemplateParameters() const {
return TemplateParams;
}
/// Get the underlying, templated declaration.
- NamedDecl *getTemplatedDecl() const { return TemplatedDecl; }
+ NamedDecl *getTemplatedDecl() const { return TemplatedDecl.getPointer(); }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -367,20 +367,30 @@
SourceRange getSourceRange() const override LLVM_READONLY {
return SourceRange(TemplateParams->getTemplateLoc(),
- TemplatedDecl->getSourceRange().getEnd());
+ TemplatedDecl.getPointer()->getSourceRange().getEnd());
}
+ /// Whether this is a (C++ Concepts TS) function concept.
+ bool isConcept() const { return TemplatedDecl.getInt(); }
+ void setConcept(bool IC) { TemplatedDecl.setInt(true); }
+
protected:
- NamedDecl *TemplatedDecl;
+ /// \brief The named declaration from which this template was instantiated.
+ /// (or null).
+ ///
+ /// The boolean value will be true to indicate that this template
+ /// (variable or function) is a concept.
+ llvm::PointerIntPair<NamedDecl *, 1, bool> TemplatedDecl;
+
TemplateParameterList* TemplateParams;
public:
/// \brief Initialize the underlying templated declaration and
/// template parameters.
void init(NamedDecl *templatedDecl, TemplateParameterList* templateParams) {
- assert(!TemplatedDecl && "TemplatedDecl already set!");
+ assert(!TemplatedDecl.getPointer() && "TemplatedDecl already set!");
assert(!TemplateParams && "TemplateParams already set!");
- TemplatedDecl = templatedDecl;
+ TemplatedDecl.setPointer(templatedDecl);
TemplateParams = templateParams;
}
};
@@ -890,7 +900,7 @@
/// Get the underlying function declaration of the template.
FunctionDecl *getTemplatedDecl() const {
- return static_cast<FunctionDecl*>(TemplatedDecl);
+ return static_cast<FunctionDecl*>(TemplatedDecl.getPointer());
}
/// Returns whether this template declaration defines the primary
@@ -1983,7 +1993,7 @@
/// \brief Get the underlying class declarations of the template.
CXXRecordDecl *getTemplatedDecl() const {
- return static_cast<CXXRecordDecl *>(TemplatedDecl);
+ return static_cast<CXXRecordDecl *>(TemplatedDecl.getPointer());
}
/// \brief Returns whether this template declaration defines the primary
@@ -2246,7 +2256,7 @@
public:
/// Get the underlying function declaration of the template.
TypeAliasDecl *getTemplatedDecl() const {
- return static_cast<TypeAliasDecl*>(TemplatedDecl);
+ return static_cast<TypeAliasDecl*>(TemplatedDecl.getPointer());
}
@@ -2809,7 +2819,7 @@
/// \brief Get the underlying variable declarations of the template.
VarDecl *getTemplatedDecl() const {
- return static_cast<VarDecl *>(TemplatedDecl);
+ return static_cast<VarDecl *>(TemplatedDecl.getPointer());
}
/// \brief Returns whether this template declaration defines the primary
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits