<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On 24 April 2018 at 19:42, Faisal Vali via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: faisalv<br>
Date: Tue Apr 24 19:42:26 2018<br>
New Revision: 330794<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=330794&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=330794&view=rev</a><br>
Log:<br>
[c++2a] [concepts] Add rudimentary parsing support for template concept declarations<br>
<br>
<br>
This patch is a tweak of changyu's patch: <a href="https://reviews.llvm.org/D40381" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D40381</a>. It differs in that the recognition of the 'concept' token is moved into the machinery that recognizes declaration-specifiers - this allows us to leverage the attribute handling machinery more seamlessly.<br></blockquote><div><br></div><div>Is that really worth it? This seems to add complexity to decl-specifier-seq / declarator parsing for a construct that has nothing to do with those things. I prefer the simpler approach in changyu's patch. I don't think the diagnostics you're producing are worthwhile -- the problem is not that "concept" can't be combined with other specifiers, it's that it's a fundamentally different kind of construct (just like "using X = ...", which it's much more like than it is like a declarator declaration).</div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
See the test file to get a sense of the basic parsing that this patch supports. <br>
<br>
There is much more work to be done before concepts are usable...<br>
<br>
Thanks Changyu!<br>
<br>
Added:<br>
cfe/trunk/test/Parser/cxx2a-<wbr>concept-declaration.cpp<br>
Removed:<br>
cfe/trunk/test/Parser/cxx-<wbr>concept-declaration.cpp<br>
Modified:<br>
cfe/trunk/include/clang/AST/<wbr>DeclTemplate.h<br>
cfe/trunk/include/clang/AST/<wbr>RecursiveASTVisitor.h<br>
cfe/trunk/include/clang/Basic/<wbr>DeclNodes.td<br>
cfe/trunk/include/clang/Basic/<wbr>DiagnosticParseKinds.td<br>
cfe/trunk/include/clang/Basic/<wbr>DiagnosticSemaKinds.td<br>
cfe/trunk/include/clang/Basic/<wbr>TemplateKinds.h<br>
cfe/trunk/include/clang/Parse/<wbr>Parser.h<br>
cfe/trunk/include/clang/Sema/<wbr>DeclSpec.h<br>
cfe/trunk/include/clang/Sema/<wbr>Sema.h<br>
cfe/trunk/include/clang/<wbr>Serialization/ASTBitCodes.h<br>
cfe/trunk/lib/AST/ASTDumper.<wbr>cpp<br>
cfe/trunk/lib/AST/DeclBase.cpp<br>
cfe/trunk/lib/AST/<wbr>DeclTemplate.cpp<br>
cfe/trunk/lib/CodeGen/CGDecl.<wbr>cpp<br>
cfe/trunk/lib/CodeGen/<wbr>CodeGenModule.cpp<br>
cfe/trunk/lib/Parse/ParseDecl.<wbr>cpp<br>
cfe/trunk/lib/Parse/<wbr>ParseDeclCXX.cpp<br>
cfe/trunk/lib/Parse/ParseObjc.<wbr>cpp<br>
cfe/trunk/lib/Parse/<wbr>ParseTemplate.cpp<br>
cfe/trunk/lib/Parse/<wbr>ParseTentative.cpp<br>
cfe/trunk/lib/Parse/Parser.cpp<br>
cfe/trunk/lib/Sema/DeclSpec.<wbr>cpp<br>
cfe/trunk/lib/Sema/SemaDecl.<wbr>cpp<br>
cfe/trunk/lib/Sema/<wbr>SemaDeclCXX.cpp<br>
cfe/trunk/lib/Sema/<wbr>SemaTemplate.cpp<br>
cfe/trunk/lib/Sema/<wbr>SemaTemplateInstantiateDecl.<wbr>cpp<br>
cfe/trunk/lib/Serialization/<wbr>ASTCommon.cpp<br>
cfe/trunk/lib/Serialization/<wbr>ASTReaderDecl.cpp<br>
cfe/trunk/lib/Serialization/<wbr>ASTWriter.cpp<br>
cfe/trunk/lib/Serialization/<wbr>ASTWriterDecl.cpp<br>
cfe/trunk/tools/libclang/<wbr>CIndex.cpp<br>
<br>
Modified: cfe/trunk/include/clang/AST/<wbr>DeclTemplate.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/AST/DeclTemplate.h?rev=<wbr>330794&r1=330793&r2=330794&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/AST/<wbr>DeclTemplate.h (original)<br>
+++ cfe/trunk/include/clang/AST/<wbr>DeclTemplate.h Tue Apr 24 19:42:26 2018<br>
@@ -3015,6 +3015,46 @@ public:<br>
static bool classofKind(Kind K) { return K == VarTemplate; }<br>
};<br>
<br>
+/// \brief Represents a C++2a ([temp] p1) concept-definition.<br>
+class ConceptDecl : public TemplateDecl {<br>
+protected:<br>
+ Expr *ConstraintExpr;<br>
+<br>
+ ConceptDecl(DeclContext *DC,<br>
+ SourceLocation NameLoc, DeclarationName Name,<br>
+ TemplateParameterList *Params,<br>
+ Expr *ConstraintExpr)<br>
+ : TemplateDecl(nullptr, Concept, DC, NameLoc, Name, Params),<br>
+ ConstraintExpr(ConstraintExpr) {};<br>
+public:<br>
+ static ConceptDecl *Create(ASTContext &C, DeclContext *DC,<br>
+ SourceLocation NameLoc, DeclarationName Name,<br>
+ TemplateParameterList *Params,<br>
+ Expr *ConstraintExpr);<br>
+ static ConceptDecl *CreateDeserialized(ASTContext &C, unsigned ID);<br>
+<br>
+ Expr *getConstraintExpr() const {<br>
+ return ConstraintExpr;<br>
+ }<br>
+<br>
+ void setConstraintExpr(Expr *CE) {<br>
+ ConstraintExpr = CE;<br>
+ }<br>
+<br>
+ SourceRange getSourceRange() const override LLVM_READONLY {<br>
+ return SourceRange(<wbr>getTemplateParameters()-><wbr>getTemplateLoc(),<br>
+ getConstraintExpr()-><wbr>getLocEnd());<br>
+ }<br>
+<br>
+ // Implement isa/cast/dyncast/etc.<br>
+ static bool classof(const Decl *D) { return classofKind(D->getKind()); }<br>
+ static bool classofKind(Kind K) { return K == Concept; }<br>
+<br>
+ friend class ASTReader;<br>
+ friend class ASTDeclReader;<br>
+ friend class ASTDeclWriter;<br>
+};<br>
+<br>
inline NamedDecl *getAsNamedDecl(<wbr>TemplateParameter P) {<br>
if (auto *PD = P.dyn_cast<<wbr>TemplateTypeParmDecl *>())<br>
return PD;<br>
<br>
Modified: cfe/trunk/include/clang/AST/<wbr>RecursiveASTVisitor.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/AST/RecursiveASTVisitor.<wbr>h?rev=330794&r1=330793&r2=<wbr>330794&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/AST/<wbr>RecursiveASTVisitor.h (original)<br>
+++ cfe/trunk/include/clang/AST/<wbr>RecursiveASTVisitor.h Tue Apr 24 19:42:26 2018<br>
@@ -1722,6 +1722,13 @@ DEF_TRAVERSE_TMPL_DECL(Class)<br>
DEF_TRAVERSE_TMPL_DECL(Var)<br>
DEF_TRAVERSE_TMPL_DECL(<wbr>Function)<br>
<br>
+DEF_TRAVERSE_DECL(<wbr>ConceptDecl, {<br>
+ TRY_TO(<wbr>TraverseTemplateParameterListH<wbr>elper(D-><wbr>getTemplateParameters()));<br>
+ TRY_TO(TraverseStmt(D-><wbr>getConstraintExpr()));<br>
+ // FIXME: Traverse all the concept specializations (once we implement forming<br>
+ // template-ids with them).<br>
+})<br>
+<br>
DEF_TRAVERSE_DECL(<wbr>TemplateTemplateParmDecl, {<br>
// D is the "T" in something like<br>
// template <template <typename> class T> class container { };<br>
<br>
Modified: cfe/trunk/include/clang/Basic/<wbr>DeclNodes.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DeclNodes.td?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Basic/DeclNodes.td?rev=<wbr>330794&r1=330793&r2=330794&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Basic/<wbr>DeclNodes.td (original)<br>
+++ cfe/trunk/include/clang/Basic/<wbr>DeclNodes.td Tue Apr 24 19:42:26 2018<br>
@@ -69,6 +69,7 @@ def Named : Decl<"named declarations", 1<br>
def TypeAliasTemplate : DDecl<RedeclarableTemplate>;<br>
def TemplateTemplateParm : DDecl<Template>;<br>
def BuiltinTemplate : DDecl<Template>;<br>
+ def Concept : DDecl<Template>;<br>
def Using : DDecl<Named>;<br>
def UsingPack : DDecl<Named>;<br>
def UsingShadow : DDecl<Named>;<br>
<br>
Modified: cfe/trunk/include/clang/Basic/<wbr>DiagnosticParseKinds.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Basic/<wbr>DiagnosticParseKinds.td?rev=<wbr>330794&r1=330793&r2=330794&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Basic/<wbr>DiagnosticParseKinds.td (original)<br>
+++ cfe/trunk/include/clang/Basic/<wbr>DiagnosticParseKinds.td Tue Apr 24 19:42:26 2018<br>
@@ -1150,6 +1150,24 @@ def err_pragma_cannot_end_force_<wbr>cuda_hos<br>
"force_cuda_host_device begin">;<br>
} // end of Parse Issue category.<br>
<br>
+let CategoryName = "Concepts Issue" in {<br>
+def err_concept_at_non_namespace_<wbr>scope : Error<<br>
+ "'concept' can only appear in namespace scope">;<br>
+<br>
+def err_concept_extra_headers : Error<<br>
+ "extraneous template parameter list in concept definition">;<br>
+def err_concept_unexpected_scope_<wbr>spec : Error<<br>
+ "invalid nested name specifier; concepts must be defined in their own namespace">;<br>
+def err_concept_nontemplate : Error<"concept definition must be a template; "<br>
+ "missing template parameter list">;<br>
+def err_concept_specialized : Error<<br>
+ "'concept' cannot be "<br>
+ "%select{explicitly specialized|partially specialized}0">;<br>
+def note_concept_specialized : Note<<br>
+ "'concept' cannot be "<br>
+ "%select{explicitly specialized|partially specialized}0">;<br>
+}<br>
+<br>
let CategoryName = "Modules Issue" in {<br>
def err_unexpected_module_decl : Error<<br>
"module declaration can only appear at the top level">;<br>
<br>
Modified: cfe/trunk/include/clang/Basic/<wbr>DiagnosticSemaKinds.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Basic/<wbr>DiagnosticSemaKinds.td?rev=<wbr>330794&r1=330793&r2=330794&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Basic/<wbr>DiagnosticSemaKinds.td (original)<br>
+++ cfe/trunk/include/clang/Basic/<wbr>DiagnosticSemaKinds.td Tue Apr 24 19:42:26 2018<br>
@@ -2387,33 +2387,16 @@ def warn_private_extern : Warning<<br>
def note_private_extern : Note<<br>
"use __attribute__((visibility(\"<wbr>hidden\"))) attribute instead">;<br>
<br>
-// C++ Concepts TS<br>
-def err_concept_wrong_decl_kind : Error<<br>
- "'concept' can only appear on the definition of a function template or variable template">;<br>
-def err_concept_decls_may_only_<wbr>appear_in_namespace_scope : Error<<br>
- "concept declarations may only appear in namespace scope">;<br>
-def err_function_concept_not_<wbr>defined : Error<<br>
- "function concept declaration must be a definition">;<br>
-def err_var_concept_not_<wbr>initialized : Error<<br>
- "variable concept declaration must be initialized">;<br>
-def err_function_concept_<wbr>exception_spec : Error<<br>
- "function concept cannot have exception specification">;<br>
-def err_concept_decl_invalid_<wbr>specifiers : Error<<br>
- "%select{variable|function}0 concept cannot be declared "<br>
- "'%select{thread_local|inline|<wbr>friend|constexpr}1'">;<br>
-def err_function_concept_with_<wbr>params : Error<<br>
- "function concept cannot have any parameters">;<br>
-def err_function_concept_bool_ret : Error<<br>
- "declared return type of function concept must be 'bool'">;<br>
-def err_variable_concept_bool_decl : Error<<br>
- "declared type of variable concept must be 'bool'">;<br>
-def err_concept_specified_<wbr>specialization : Error<<br>
- "'concept' cannot be applied on an "<br>
- "%select{explicit instantiation|explicit specialization|partial specialization}0">;<br>
-def err_concept_specialized : Error<<br>
- "%select{function|variable}0 concept cannot be "<br>
- "%select{explicitly instantiated|explicitly specialized|partially specialized}1">;<br>
+// C++ Concepts<br>
<br>
+<br>
+<br>
+def err_concept_initialized_with_<wbr>non_bool_type : Error<<br>
+ "type of constraint expression must be 'bool' - not '%0'">;<br>
+def err_concept_no_associated_<wbr>constraints : Error<<br>
+ "concept may not have associated constraints">;<br>
+def err_concept_feature_<wbr>unimplemented : Error<<br>
+ "unimplemented concept feature: %0 (coming soon)">;<br>
def err_template_different_<wbr>associated_constraints : Error<<br>
"associated constraints differ in template redeclaration">;<br>
<br>
<br>
Modified: cfe/trunk/include/clang/Basic/<wbr>TemplateKinds.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TemplateKinds.h?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Basic/TemplateKinds.h?<wbr>rev=330794&r1=330793&r2=<wbr>330794&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Basic/<wbr>TemplateKinds.h (original)<br>
+++ cfe/trunk/include/clang/Basic/<wbr>TemplateKinds.h Tue Apr 24 19:42:26 2018<br>
@@ -43,10 +43,10 @@ enum TemplateNameKind {<br>
/// whether the template name is assumed to refer to a type template or a<br>
/// function template depends on the context in which the template<br>
/// name occurs.<br>
- TNK_Dependent_template_name<br>
+ TNK_Dependent_template_name,<br>
+ /// The name refers to a concept definition.<br>
+ TNK_Concept_template<br>
};<br>
<br>
}<br>
#endif<br>
-<br>
-<br>
<br>
Modified: cfe/trunk/include/clang/Parse/<wbr>Parser.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Parse/Parser.h?rev=<wbr>330794&r1=330793&r2=330794&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Parse/<wbr>Parser.h (original)<br>
+++ cfe/trunk/include/clang/Parse/<wbr>Parser.h Tue Apr 24 19:42:26 2018<br>
@@ -1959,7 +1959,16 @@ private:<br>
ParsedAttributesWithRange &Attrs);<br>
DeclSpecContext<br>
getDeclSpecContextFromDeclarat<wbr>orContext(DeclaratorContext Context);<br>
- void ParseDeclarationSpecifiers(<br>
+<br>
+ /// \brief Parses declaration-specifiers upto a declarator or ';' emitting<br>
+ /// diagnostics as necessary and storing parsed information within DS.<br>
+ ///<br>
+ /// Note: Asides from parsing the routine C/C++ decl-specifiers (which could<br>
+ /// include entire class or enum definitions), this also parses a concept<br>
+ /// definition and stores the appropriate AST representations (for<br>
+ /// class/enum/concept declarations/definitions, decltype<br>
+ /// expression-operands or types, where appropriate) within DS.<br>
+ void ParseDeclarationSpecifiersOrCo<wbr>nceptDefinition(<br>
DeclSpec &DS,<br>
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),<br>
AccessSpecifier AS = AS_none,<br>
@@ -2811,6 +2820,11 @@ private:<br>
SourceLocation &DeclEnd,<br>
AccessSpecifier AS = AS_none);<br>
<br>
+ /// \brief Parse a single template declaration that declares a concept [c++2a]<br>
+ /// and store the AST node within DS.<br>
+ void ParseConceptDefinition(<wbr>SourceLocation ConceptLoc, DeclSpec &DS,<br>
+ const ParsedTemplateInfo &TemplateInfo,<br>
+ AccessSpecifier AS, DeclSpecContext DSC);<br>
//===-------------------------<wbr>------------------------------<wbr>-------------===//<br>
// Modules<br>
DeclGroupPtrTy ParseModuleDecl();<br>
<br>
Modified: cfe/trunk/include/clang/Sema/<wbr>DeclSpec.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Sema/DeclSpec.h?rev=<wbr>330794&r1=330793&r2=330794&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Sema/<wbr>DeclSpec.h (original)<br>
+++ cfe/trunk/include/clang/Sema/<wbr>DeclSpec.h Tue Apr 24 19:42:26 2018<br>
@@ -38,6 +38,7 @@<br>
namespace clang {<br>
class ASTContext;<br>
class CXXRecordDecl;<br>
+ class ConceptDecl;<br>
class TypeLoc;<br>
class LangOptions;<br>
class IdentifierInfo;<br>
@@ -221,10 +222,13 @@ public:<br>
unsigned location_size() const { return Builder.getBuffer().second; }<br>
};<br>
<br>
-/// \brief Captures information about "declaration specifiers".<br>
+/// \brief Captures information about "decl-specifiers" and also concept<br>
+/// definitions.<br>
///<br>
/// "Declaration specifiers" encompasses storage-class-specifiers,<br>
-/// type-specifiers, type-qualifiers, and function-specifiers.<br>
+/// type-specifiers, type-qualifiers, and function-specifiers. This includes<br>
+/// class and enum definitions whose AST representations must be stored - same<br>
+/// with the expression-operands of decltype.<br>
class DeclSpec {<br>
public:<br>
/// \brief storage-class-specifier<br>
@@ -363,8 +367,14 @@ private:<br>
unsigned Constexpr_specified : 1;<br>
<br>
union {<br>
+ // Valid if isTypeRep is true.<br>
UnionParsedType TypeRep;<br>
+ // If we parsed a concept, class, enum (etc.) defintion or elaborated type<br>
+ // specifier, this stores the AST representation. This is valid if either<br>
+ // isDeclRep or isConceptSpecified returns true.<br>
Decl *DeclRep;<br>
+ // If we parsed a typeof(e) or decltype(e) operator, this stores the<br>
+ // expression 'e'. Valid if isExprRep is true.<br>
Expr *ExprRep;<br>
};<br>
<br>
@@ -393,6 +403,11 @@ private:<br>
SourceLocation FS_forceinlineLoc;<br>
SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc;<br>
SourceLocation TQ_pipeLoc;<br>
+ <br>
+ // Even though 'concept' is not a specifier, we handle it here. This allows us<br>
+ // to reuse infrastructure for diagnosing attributes and invalid<br>
+ // decl-specifiers.<br>
+ SourceLocation ConceptLoc;<br>
<br>
WrittenBuiltinSpecs writtenBS;<br>
void SaveWrittenBuiltinSpecs();<br>
@@ -482,7 +497,10 @@ public:<br>
bool isTypeSpecOwned() const { return TypeSpecOwned; }<br>
bool isTypeRep() const { return isTypeRep((TST) TypeSpecType); }<br>
bool isTypeSpecPipe() const { return TypeSpecPipe; }<br>
-<br>
+ bool isDeclRep() const {<br>
+ return isDeclRep((TST)TypeSpecType);<br>
+ }<br>
+ <br>
ParsedType getRepAsType() const {<br>
assert(isTypeRep((TST) TypeSpecType) && "DeclSpec does not store a type");<br>
return TypeRep;<br>
@@ -491,6 +509,17 @@ public:<br>
assert(isDeclRep((TST) TypeSpecType) && "DeclSpec does not store a decl");<br>
return DeclRep;<br>
}<br>
+ // This is a template that should only be instantiated with the type<br>
+ // ConceptDecl. By making it a template we only require ConceptDecl to be a<br>
+ // complete type where this function is called.<br>
+ template<class ConceptDeclTy = ConceptDecl><br>
+ ConceptDeclTy *getRepAsConcept() const {<br>
+ static_assert(std::is_same<<wbr>ConceptDeclTy, ConceptDecl>::value,<br>
+ "Must only be instantiated with ConceptDecl");<br>
+ assert(isConceptSpecified() && "DeclSpec does not store a concept");<br>
+<br>
+ return cast_or_null<ConceptDeclTy>(<wbr>DeclRep);<br>
+ }<br>
Expr *getRepAsExpr() const {<br>
assert(isExprRep((TST) TypeSpecType) && "DeclSpec does not store an expr");<br>
return ExprRep;<br>
@@ -665,6 +694,19 @@ public:<br>
assert(isDeclRep((TST) TypeSpecType));<br>
DeclRep = Rep;<br>
}<br>
+ // This function can only be instantiated with ConceptDecl. We made it a<br>
+ // template so that ConceptDecl only has to be defined where this is called.<br>
+ template <class ConceptDeclTy = ConceptDecl><br>
+ void setConceptRep(ConceptDecl *Rep) {<br>
+ static_assert(std::is_same<<wbr>ConceptDeclTy, ConceptDecl>::value,<br>
+ "Must only be instantiated with ConceptDecl");<br>
+ assert(isConceptSpecified() && "DeclSpec does not store a concept");<br>
+ assert(!DeclRep &&<br>
+ "why is this not null? We expect this function to be called only "<br>
+ "once, and usually right after DeclRep was set to null");<br>
+ DeclRep = Rep;<br>
+ }<br>
+ <br>
void UpdateTypeRep(ParsedType Rep) {<br>
assert(isTypeRep((TST) TypeSpecType));<br>
TypeRep = Rep;<br>
@@ -694,6 +736,8 @@ public:<br>
unsigned &DiagID);<br>
bool SetConstexprSpec(<wbr>SourceLocation Loc, const char *&PrevSpec,<br>
unsigned &DiagID);<br>
+ bool setConceptSpec(SourceLocation Loc, const char *&PrevSpec,<br>
+ unsigned &DiagID, const PrintingPolicy &P);<br>
<br>
bool isFriendSpecified() const { return Friend_specified; }<br>
SourceLocation getFriendSpecLoc() const { return FriendLoc; }<br>
@@ -704,6 +748,8 @@ public:<br>
bool isConstexprSpecified() const { return Constexpr_specified; }<br>
SourceLocation getConstexprSpecLoc() const { return ConstexprLoc; }<br>
<br>
+ bool isConceptSpecified() const { return ConceptLoc.isValid(); }<br>
+ SourceLocation getConceptLoc() const { return ConceptLoc; }<br>
void ClearConstexprSpec() {<br>
Constexpr_specified = false;<br>
ConstexprLoc = SourceLocation();<br>
<br>
Modified: cfe/trunk/include/clang/Sema/<wbr>Sema.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Sema/Sema.h?rev=330794&<wbr>r1=330793&r2=330794&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Sema/<wbr>Sema.h (original)<br>
+++ cfe/trunk/include/clang/Sema/<wbr>Sema.h Tue Apr 24 19:42:26 2018<br>
@@ -2126,6 +2126,7 @@ public:<br>
<br>
Decl *ParsedFreeStandingDeclSpec(<wbr>Scope *S, AccessSpecifier AS, DeclSpec &DS,<br>
RecordDecl *&AnonRecord);<br>
+<br>
Decl *ParsedFreeStandingDeclSpec(<wbr>Scope *S, AccessSpecifier AS, DeclSpec &DS,<br>
MultiTemplateParamsArg TemplateParams,<br>
bool IsExplicitInstantiation,<br>
@@ -6229,6 +6230,13 @@ public:<br>
SourceLocation TemplateLoc,<br>
const TemplateArgumentListInfo *TemplateArgs);<br>
<br>
+ ExprResult<br>
+ CheckConceptTemplateId(const CXXScopeSpec &SS,<br>
+ const DeclarationNameInfo &NameInfo,<br>
+ ConceptDecl *Template,<br>
+ SourceLocation TemplateLoc,<br>
+ const TemplateArgumentListInfo *TemplateArgs);<br>
+<br>
ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS,<br>
SourceLocation TemplateKWLoc,<br>
LookupResult &R,<br>
@@ -6507,6 +6515,13 @@ public:<br>
const TemplateArgument *Args,<br>
unsigned NumArgs);<br>
<br>
+ // Concepts<br>
+ ConceptDecl *ActOnConceptDefinition(<br>
+ Scope *S,<br>
+ MultiTemplateParamsArg TemplateParameterLists,<br>
+ IdentifierInfo *Name, SourceLocation NameLoc,<br>
+ Expr *ConstraintExpr);<br>
+<br>
//===-------------------------<wbr>------------------------------<wbr>-------------===//<br>
// C++ Variadic Templates (C++0x [temp.variadic])<br>
//===-------------------------<wbr>------------------------------<wbr>-------------===//<br>
<br>
Modified: cfe/trunk/include/clang/<wbr>Serialization/ASTBitCodes.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Serialization/<wbr>ASTBitCodes.h?rev=330794&r1=<wbr>330793&r2=330794&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/<wbr>Serialization/ASTBitCodes.h (original)<br>
+++ cfe/trunk/include/clang/<wbr>Serialization/ASTBitCodes.h Tue Apr 24 19:42:26 2018<br>
@@ -1408,6 +1408,9 @@ namespace serialization {<br>
/// \brief A TypeAliasTemplateDecl record.<br>
DECL_TYPE_ALIAS_TEMPLATE,<br>
<br>
+ /// \brief A ConceptDecl record.<br>
+ DECL_CONCEPT,<br>
+<br>
/// \brief A StaticAssertDecl record.<br>
DECL_STATIC_ASSERT,<br>
<br>
<br>
Modified: cfe/trunk/lib/AST/ASTDumper.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTDumper.cpp?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/AST/<wbr>ASTDumper.cpp?rev=330794&r1=<wbr>330793&r2=330794&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/AST/ASTDumper.<wbr>cpp (original)<br>
+++ cfe/trunk/lib/AST/ASTDumper.<wbr>cpp Tue Apr 24 19:42:26 2018<br>
@@ -466,6 +466,7 @@ namespace {<br>
bool DumpRefOnly);<br>
template<typename TemplateDecl><br>
void VisitTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst);<br>
+ void VisitConceptDecl(const ConceptDecl *D);<br>
void VisitFunctionTemplateDecl(<wbr>const FunctionTemplateDecl *D);<br>
void VisitClassTemplateDecl(const ClassTemplateDecl *D);<br>
void VisitClassTemplateSpecializati<wbr>onDecl(<br>
@@ -1577,6 +1578,12 @@ void ASTDumper::VisitTemplateDecl(<wbr>const<br>
!D->isCanonicalDecl());<br>
}<br>
<br>
+void ASTDumper::VisitConceptDecl(<wbr>const ConceptDecl *D) {<br>
+ dumpName(D);<br>
+ dumpTemplateParameters(D-><wbr>getTemplateParameters());<br>
+ dumpStmt(D->getConstraintExpr(<wbr>));<br>
+}<br>
+<br>
void ASTDumper::<wbr>VisitFunctionTemplateDecl(<wbr>const FunctionTemplateDecl *D) {<br>
// FIXME: We don't add a declaration of a function template specialization<br>
// to its context when it's explicitly instantiated, so dump explicit<br>
<br>
Modified: cfe/trunk/lib/AST/DeclBase.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/AST/<wbr>DeclBase.cpp?rev=330794&r1=<wbr>330793&r2=330794&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/AST/DeclBase.cpp (original)<br>
+++ cfe/trunk/lib/AST/DeclBase.cpp Tue Apr 24 19:42:26 2018<br>
@@ -724,6 +724,7 @@ unsigned Decl::<wbr>getIdentifierNamespaceFor<br>
case Binding:<br>
case NonTypeTemplateParm:<br>
case VarTemplate:<br>
+ case Concept:<br>
// These (C++-only) declarations are found by redeclaration lookup for<br>
// tag types, so we include them in the tag namespace.<br>
return IDNS_Ordinary | IDNS_Tag;<br>
<br>
Modified: cfe/trunk/lib/AST/<wbr>DeclTemplate.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclTemplate.cpp?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/AST/<wbr>DeclTemplate.cpp?rev=330794&<wbr>r1=330793&r2=330794&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/AST/<wbr>DeclTemplate.cpp (original)<br>
+++ cfe/trunk/lib/AST/<wbr>DeclTemplate.cpp Tue Apr 24 19:42:26 2018<br>
@@ -789,6 +789,27 @@ ClassTemplateSpecializationDec<wbr>l::getSour<br>
}<br>
<br>
//===-------------------------<wbr>------------------------------<wbr>---------------===//<br>
+// ConceptDecl Implementation<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
+ConceptDecl *ConceptDecl::Create(<wbr>ASTContext &C, DeclContext *DC,<br>
+ SourceLocation NameLoc, DeclarationName Name,<br>
+ TemplateParameterList *Params,<br>
+ Expr *ConstraintExpr) {<br>
+ // TODO: Do we need this?<br>
+ // AdoptTemplateParameterList(<wbr>Params, cast<DeclContext>(Decl));<br>
+ return new (C, DC) ConceptDecl(DC, NameLoc, Name, Params, ConstraintExpr);<br>
+}<br>
+<br>
+ConceptDecl *ConceptDecl::<wbr>CreateDeserialized(ASTContext &C,<br>
+ unsigned ID) {<br>
+ ConceptDecl *Result = new (C, ID) ConceptDecl(nullptr, SourceLocation(),<br>
+ DeclarationName(),<br>
+ nullptr, nullptr);<br>
+<br>
+ return Result;<br>
+}<br>
+<br>
+//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
// ClassTemplatePartialSpecializa<wbr>tionDecl Implementation<br>
//===-------------------------<wbr>------------------------------<wbr>---------------===//<br>
void ClassTemplatePartialSpecializa<wbr>tionDecl::anchor() {}<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGDecl.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/CodeGen/<wbr>CGDecl.cpp?rev=330794&r1=<wbr>330793&r2=330794&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/CodeGen/CGDecl.<wbr>cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGDecl.<wbr>cpp Tue Apr 24 19:42:26 2018<br>
@@ -105,6 +105,7 @@ void CodeGenFunction::EmitDecl(<wbr>const Dec<br>
case Decl::OMPThreadPrivate:<br>
case Decl::OMPCapturedExpr:<br>
case Decl::Empty:<br>
+ case Decl::Concept:<br>
// None of these decls require codegen support.<br>
return;<br>
<br>
<br>
Modified: cfe/trunk/lib/CodeGen/<wbr>CodeGenModule.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/CodeGen/<wbr>CodeGenModule.cpp?rev=330794&<wbr>r1=330793&r2=330794&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/CodeGen/<wbr>CodeGenModule.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/<wbr>CodeGenModule.cpp Tue Apr 24 19:42:26 2018<br>
@@ -4423,6 +4423,7 @@ void CodeGenModule::<wbr>EmitTopLevelDecl(Dec<br>
case Decl::TypeAliasTemplate:<br>
case Decl::Block:<br>
case Decl::Empty:<br>
+ case Decl::Concept:<br>
break;<br>
case Decl::Using: // using X; [C++]<br>
if (CGDebugInfo *DI = getModuleDebugInfo())<br>
<br>
Modified: cfe/trunk/lib/Parse/ParseDecl.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Parse/<wbr>ParseDecl.cpp?rev=330794&r1=<wbr>330793&r2=330794&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Parse/ParseDecl.<wbr>cpp (original)<br>
+++ cfe/trunk/lib/Parse/ParseDecl.<wbr>cpp Tue Apr 24 19:42:26 2018<br>
@@ -1739,7 +1739,8 @@ Parser::<wbr>ParseSimpleDeclaration(<wbr>Declarato<br>
ParsingDeclSpec DS(*this);<br>
<br>
DeclSpecContext DSContext = getDeclSpecContextFromDeclarat<wbr>orContext(Context);<br>
- ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none, DSContext);<br>
+ ParseDeclarationSpecifiersOrCo<wbr>nceptDefinition(DS, ParsedTemplateInfo(),<br>
+ AS_none, DSContext);<br>
<br>
// If we had a free-standing type definition with a missing semicolon, we<br>
// may get this far before the problem becomes obvious.<br>
@@ -2386,7 +2387,8 @@ void Parser::<wbr>ParseSpecifierQualifierList<br>
/// specifier-qualifier-list is a subset of declaration-specifiers. Just<br>
/// parse declaration-specifiers and complain about extra stuff.<br>
/// TODO: diagnose attribute-specifiers and alignment-specifiers.<br>
- ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS, DSC);<br>
+ ParseDeclarationSpecifiersOrCo<wbr>nceptDefinition(DS, ParsedTemplateInfo(), AS,<br>
+ DSC);<br>
<br>
// Validate declspec for type-name.<br>
unsigned Specs = DS.getParsedSpecifiers();<br>
@@ -2871,11 +2873,12 @@ Parser::<wbr>DiagnoseMissingSemiAfterTagDef<wbr>in<br>
// and call ParsedFreeStandingDeclSpec as appropriate.<br>
DS.ClearTypeSpecType();<br>
ParsedTemplateInfo NotATemplate;<br>
- ParseDeclarationSpecifiers(DS, NotATemplate, AS, DSContext, LateAttrs);<br>
+ ParseDeclarationSpecifiersOrCo<wbr>nceptDefinition(DS, NotATemplate, AS, DSContext,<br>
+ LateAttrs);<br>
return false;<br>
}<br>
<br>
-/// ParseDeclarationSpecifiers<br>
+/// ParseDeclarationSpecifiersOrCo<wbr>nceptDefinition<br>
/// declaration-specifiers: [C99 6.7]<br>
/// storage-class-specifier declaration-specifiers[opt]<br>
/// type-specifier declaration-specifiers[opt]<br>
@@ -2902,7 +2905,8 @@ Parser::<wbr>DiagnoseMissingSemiAfterTagDef<wbr>in<br>
/// [OpenCL] '__kernel'<br>
/// 'friend': [C++ dcl.friend]<br>
/// 'constexpr': [C++0x dcl.constexpr]<br>
-void Parser::<wbr>ParseDeclarationSpecifiers(<wbr>DeclSpec &DS,<br>
+/// [C++2a] 'concept'<br>
+void Parser::<wbr>ParseDeclarationSpecifiersOrCo<wbr>nceptDefinition(DeclSpec &DS,<br>
const ParsedTemplateInfo &TemplateInfo,<br>
AccessSpecifier AS,<br>
DeclSpecContext DSContext,<br>
@@ -3680,7 +3684,11 @@ void Parser::<wbr>ParseDeclarationSpecifiers(<br>
ConsumeToken();<br>
ParseEnumSpecifier(Loc, DS, TemplateInfo, AS, DSContext);<br>
continue;<br>
-<br>
+ <br>
+ case tok::kw_concept:<br>
+ ConsumeToken();<br>
+ ParseConceptDefinition(Loc, DS, TemplateInfo, AS, DSContext);<br>
+ continue;<br>
// cv-qualifier:<br>
case tok::kw_const:<br>
isInvalid = DS.SetTypeQual(DeclSpec::TQ_<wbr>const, Loc, PrevSpec, DiagID,<br>
@@ -6366,7 +6374,7 @@ void Parser::<wbr>ParseParameterDeclarationCl<br>
// too much hassle.<br>
DS.takeAttributesFrom(<wbr>FirstArgAttrs);<br>
<br>
- ParseDeclarationSpecifiers(DS)<wbr>;<br>
+ ParseDeclarationSpecifiersOrCo<wbr>nceptDefinition(DS);<br>
<br>
<br>
// Parse the declarator. This is "PrototypeContext" or <br>
<br>
Modified: cfe/trunk/lib/Parse/<wbr>ParseDeclCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Parse/<wbr>ParseDeclCXX.cpp?rev=330794&<wbr>r1=330793&r2=330794&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Parse/<wbr>ParseDeclCXX.cpp (original)<br>
+++ cfe/trunk/lib/Parse/<wbr>ParseDeclCXX.cpp Tue Apr 24 19:42:26 2018<br>
@@ -2561,8 +2561,8 @@ Parser::<wbr>ParseCXXClassMemberDeclaration<wbr>(A<br>
if (MalformedTypeSpec)<br>
DS.SetTypeSpecError();<br>
<br>
- ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DeclSpecContext::DSC_class,<br>
- &CommonLateParsedAttrs);<br>
+ ParseDeclarationSpecifiersOrCo<wbr>nceptDefinition(<br>
+ DS, TemplateInfo, AS, DeclSpecContext::DSC_class, &CommonLateParsedAttrs);<br>
<br>
// Turn off colon protection that was set for declspec.<br>
X.restore();<br>
<br>
Modified: cfe/trunk/lib/Parse/ParseObjc.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Parse/<wbr>ParseObjc.cpp?rev=330794&r1=<wbr>330793&r2=330794&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Parse/ParseObjc.<wbr>cpp (original)<br>
+++ cfe/trunk/lib/Parse/ParseObjc.<wbr>cpp Tue Apr 24 19:42:26 2018<br>
@@ -1490,7 +1490,7 @@ Decl *Parser::ParseObjCMethodDecl(<wbr>Source<br>
cStyleParamWarned = true;<br>
}<br>
DeclSpec DS(AttrFactory);<br>
- ParseDeclarationSpecifiers(DS)<wbr>;<br>
+ ParseDeclarationSpecifiersOrCo<wbr>nceptDefinition(DS);<br>
// Parse the declarator.<br>
Declarator ParmDecl(DS, DeclaratorContext::<wbr>PrototypeContext);<br>
ParseDeclarator(ParmDecl);<br>
@@ -2541,7 +2541,7 @@ StmtResult Parser::ParseObjCTryStmt(Sour<br>
Scope::AtCatchScope);<br>
if (Tok.isNot(tok::ellipsis)) {<br>
DeclSpec DS(AttrFactory);<br>
- ParseDeclarationSpecifiers(DS)<wbr>;<br>
+ ParseDeclarationSpecifiersOrCo<wbr>nceptDefinition(DS);<br>
Declarator ParmDecl(DS, DeclaratorContext::<wbr>ObjCCatchContext);<br>
ParseDeclarator(ParmDecl);<br>
<br>
<br>
Modified: cfe/trunk/lib/Parse/<wbr>ParseTemplate.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTemplate.cpp?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Parse/<wbr>ParseTemplate.cpp?rev=330794&<wbr>r1=330793&r2=330794&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Parse/<wbr>ParseTemplate.cpp (original)<br>
+++ cfe/trunk/lib/Parse/<wbr>ParseTemplate.cpp Tue Apr 24 19:42:26 2018<br>
@@ -54,6 +54,15 @@ Parser::<wbr>ParseDeclarationStartingWithTe<wbr>mp<br>
/// template-declaration: [C++ temp]<br>
/// 'export'[opt] 'template' '<' template-parameter-list '>' declaration<br>
///<br>
+/// template-declaration: [C++2a]<br>
+/// template-head declaration<br>
+/// template-head concept-definition<br>
+///<br>
+/// TODO: requires-clause<br>
+/// template-head: [C++2a]<br>
+/// 'export'[opt] 'template' '<' template-parameter-list '>'<br>
+/// requires-clause[opt]<br>
+///<br>
/// explicit-specialization: [ C++ temp.expl.spec]<br>
/// 'template' '<' '>' declaration<br>
Decl *<br>
@@ -148,13 +157,10 @@ Parser::<wbr>ParseTemplateDeclarationOrSpec<wbr>ia<br>
unsigned NewFlags = getCurScope()->getFlags() & ~Scope::TemplateParamScope;<br>
ParseScopeFlags TemplateScopeFlags(this, NewFlags, isSpecialization);<br>
<br>
- // Parse the actual template declaration.<br>
- return ParseSingleDeclarationAfterTem<wbr>plate(Context,<br>
- ParsedTemplateInfo(&<wbr>ParamLists,<br>
- isSpecialization,<br>
- LastParamListWasEmpty),<br>
- ParsingTemplateParams,<br>
- DeclEnd, AS, AccessAttrs);<br>
+ return ParseSingleDeclarationAfterTem<wbr>plate(<br>
+ Context,<br>
+ ParsedTemplateInfo(&<wbr>ParamLists, isSpecialization, LastParamListWasEmpty),<br>
+ ParsingTemplateParams, DeclEnd, AS, AccessAttrs);<br>
}<br>
<br>
/// \brief Parse a single declaration that declares a template,<br>
@@ -208,7 +214,7 @@ Parser::<wbr>ParseSingleDeclarationAfterTem<wbr>pl<br>
// the template parameters.<br>
ParsingDeclSpec DS(*this, &DiagsFromTParams);<br>
<br>
- ParseDeclarationSpecifiers(DS, TemplateInfo, AS,<br>
+ ParseDeclarationSpecifiersOrCo<wbr>nceptDefinition(DS, TemplateInfo, AS,<br>
getDeclSpecContextFromDeclarat<wbr>orContext(Context));<br>
<br>
if (Tok.is(tok::semi)) {<br>
@@ -322,6 +328,149 @@ Parser::<wbr>ParseSingleDeclarationAfterTem<wbr>pl<br>
return ThisDecl;<br>
}<br>
<br>
+<br>
+void<br>
+Parser::<wbr>ParseConceptDefinition(<wbr>SourceLocation ConceptLoc,<br>
+ DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo,<br>
+ AccessSpecifier AS, <br>
+ DeclSpecContext DSC) {<br>
+<br>
+ <br>
+ auto DiagnoseAttributes = [this] {<br>
+ ParsedAttributesWithRange attrs(this->AttrFactory);<br>
+ this->MaybeParseGNUAttributes(<wbr>attrs);<br>
+ this-><wbr>MaybeParseCXX11Attributes(<wbr>attrs);<br>
+ this-><wbr>MaybeParseMicrosoftDeclSpecs(<wbr>attrs);<br>
+ this->ProhibitAttributes(<wbr>attrs);<br>
+ };<br>
+<br>
+<br>
+ // If attributes exist after 'concept' kw but before the concept name,<br>
+ // prohibit them for now (if CWG approves attributes on concepts, this is<br>
+ // likely where they will go...).<br>
+ DiagnoseAttributes();<br>
+<br>
+ // Set the concept specifier at ConceptLoc within 'DS' along with emitting any<br>
+ // incompatible decl-specifier diagnostics.<br>
+ {<br>
+ const char *PrevSpec = 0;<br>
+ unsigned int DiagId = 0;<br>
+ if (DS.setConceptSpec(ConceptLoc, PrevSpec, DiagId,<br>
+ Actions.getASTContext().<wbr>getPrintingPolicy())) {<br>
+ Diag(ConceptLoc, DiagId) << PrevSpec;<br>
+ }<br>
+ Actions.<wbr>DiagnoseFunctionSpecifiers(DS)<wbr>;<br>
+ }<br>
+<br>
+ if (DSC != DeclSpecContext::DSC_top_<wbr>level) {<br>
+ Diag(ConceptLoc, diag::err_concept_at_non_<wbr>namespace_scope);<br>
+ // If we are not in a template parameter context, skip to a '}' or ';'. The<br>
+ // error messages are better if we just ignore this within template<br>
+ // parameter lists.<br>
+ if (DSC != DeclSpecContext::DSC_template_<wbr>param) {<br>
+ SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);<br>
+ } else {<br>
+ SkipUntil(llvm::makeArrayRef({<wbr>tok::comma, tok::greater}),<br>
+ StopAtSemi | StopBeforeMatch);<br>
+ }<br>
+ return;<br>
+ }<br>
+<br>
+ // A scope-guard that (if an error occurs while parsing a concept) skips to<br>
+ // the next semi or closing brace.<br>
+ class SkipUntilSemiOrClosingBraceOnS<wbr>copeExit {<br>
+ Parser &P;<br>
+ bool Disabled = false;<br>
+<br>
+ public:<br>
+ SkipUntilSemiOrClosingBraceOnS<wbr>copeExit(Parser &P)<br>
+ : P(P) {}<br>
+ void disable() { Disabled = true; }<br>
+ ~<wbr>SkipUntilSemiOrClosingBraceOnS<wbr>copeExit() {<br>
+ if (!Disabled) {<br>
+ // Skip until the semi-colon or a '}'.<br>
+ P.SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch);<br>
+ }<br>
+ }<br>
+ } SkipUntilSemiOrClosingBraceOnS<wbr>copeExit(*this);<br>
+<br>
+ if (TemplateInfo.Kind == ParsedTemplateInfo::<wbr>NonTemplate) {<br>
+ Diag(ConceptLoc, diag::err_concept_nontemplate)<wbr>;<br>
+ return;<br>
+ }<br>
+ <br>
+ const TemplateParameterLists &ParamLists = *TemplateInfo.TemplateParams;<br>
+<br>
+ <br>
+ // More than one TPL wouldn't make sense here.<br>
+ if (ParamLists.size() != 1) {<br>
+ Diag(Tok.getLocation(), diag::err_concept_extra_<wbr>headers);<br>
+ return;<br>
+ }<br>
+ const TemplateParameterList *const TPL = ParamLists[0];<br>
+<br>
+ // Explicit specializations of concepts are not allowed.<br>
+ if (TPL->getLAngleLoc().<wbr>getLocWithOffset(1) == TPL->getRAngleLoc()) {<br>
+ assert(!TPL->size() &&<br>
+ "can not have template parameters within empty angle brackets!");<br>
+ Diag(ConceptLoc, diag::err_concept_specialized) << 0;<br>
+ return;<br>
+ }<br>
+ // Concepts can not be defined with nested name specifiers.<br>
+ CXXScopeSpec SS;<br>
+ if (<wbr>ParseOptionalCXXScopeSpecifier<wbr>(SS, nullptr,<br>
+ /*EnteringContext=*/false) ||<br>
+ SS.isNotEmpty()) {<br>
+<br>
+ if (SS.isNotEmpty())<br>
+ Diag(Tok.getLocation(), diag::err_concept_unexpected_<wbr>scope_spec);<br>
+ return;<br>
+ }<br>
+ // An identifier (i.e. the concept-name) should follow 'concept'.<br>
+ if (!Tok.is(tok::identifier)) {<br>
+ Diag(Tok.getLocation(), diag::err_expected) << "concept name";<br>
+ return;<br>
+ }<br>
+<br>
+ IdentifierInfo *Id = Tok.getIdentifierInfo();<br>
+ SourceLocation IdLoc = ConsumeToken();<br>
+ <br>
+ // If attributes exist after the identifier, parse them and diagnose<br>
+ DiagnoseAttributes();<br>
+<br>
+ if (!TryConsumeToken(tok::equal)) {<br>
+ Diag(Tok.getLocation(), diag::err_expected) << "equal";<br>
+ return;<br>
+ }<br>
+<br>
+ ExprResult ConstraintExprResult = ParseConstraintExpression();<br>
+ if (ConstraintExprResult.<wbr>isInvalid()) {<br>
+ Diag(Tok.getLocation(), diag::err_expected_expression)<br>
+ << "constraint-expression";<br>
+ return;<br>
+ }<br>
+<br>
+ // We can try to create a valid concept decl node now, so disable the<br>
+ // scope-guard.<br>
+ SkipUntilSemiOrClosingBraceOnS<wbr>copeExit.disable();<br>
+<br>
+ Expr *ConstraintExpr = ConstraintExprResult.get();<br>
+ ConceptDecl *const ConDecl = Actions.<wbr>ActOnConceptDefinition(<br>
+ getCurScope(), *TemplateInfo.TemplateParams, Id, IdLoc, ConstraintExpr);<br>
+ DS.setConceptRep(ConDecl);<br>
+<br>
+ if (Tok.isNot(tok::semi)) {<br>
+ <br>
+ ExpectAndConsume(tok::semi, diag::err_expected_after, "concept");<br>
+ // Push this token back into the preprocessor and change our current token<br>
+ // to ';' so that the rest of the code recovers as though there were an<br>
+ // ';' after the definition.<br>
+ PP.EnterToken(Tok);<br>
+ Tok.setKind(tok::semi);<br>
+ }<br>
+ return;<br>
+}<br>
+<br>
/// ParseTemplateParameters - Parses a template-parameter-list enclosed in<br>
/// angle brackets. Depth is the depth of this template-parameter-list, which<br>
/// is the number of template headers directly enclosing this template header.<br>
@@ -690,8 +839,8 @@ Parser::<wbr>ParseNonTypeTemplateParameter(<wbr>un<br>
// FIXME: The type should probably be restricted in some way... Not all<br>
// declarators (parts of declarators?) are accepted for parameters.<br>
DeclSpec DS(AttrFactory);<br>
- ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none,<br>
- DeclSpecContext::DSC_template_<wbr>param);<br>
+ ParseDeclarationSpecifiersOrCo<wbr>nceptDefinition(<br>
+ DS, ParsedTemplateInfo(), AS_none, DeclSpecContext::DSC_template_<wbr>param);<br>
<br>
// Parse this as a typename.<br>
Declarator ParamDecl(DS, DeclaratorContext::<wbr>TemplateParamContext);<br>
<br>
Modified: cfe/trunk/lib/Parse/<wbr>ParseTentative.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseTentative.cpp?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Parse/<wbr>ParseTentative.cpp?rev=330794&<wbr>r1=330793&r2=330794&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Parse/<wbr>ParseTentative.cpp (original)<br>
+++ cfe/trunk/lib/Parse/<wbr>ParseTentative.cpp Tue Apr 24 19:42:26 2018<br>
@@ -1351,6 +1351,7 @@ Parser::<wbr>isCXXDeclarationSpecifier(<wbr>Parser<br>
case tok::kw_struct:<br>
case tok::kw_union:<br>
case tok::kw___interface:<br>
+ case tok::kw_concept:<br>
// enum-specifier<br>
case tok::kw_enum:<br>
// cv-qualifier<br>
<br>
Modified: cfe/trunk/lib/Parse/Parser.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Parse/<wbr>Parser.cpp?rev=330794&r1=<wbr>330793&r2=330794&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Parse/Parser.cpp (original)<br>
+++ cfe/trunk/lib/Parse/Parser.cpp Tue Apr 24 19:42:26 2018<br>
@@ -919,7 +919,7 @@ Parser::<wbr>ParseDeclOrFunctionDefInternal<wbr>(P<br>
AccessSpecifier AS) {<br>
MaybeParseMicrosoftAttributes(<wbr>DS.getAttributes());<br>
// Parse the common declaration-specifiers piece.<br>
- ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS,<br>
+ ParseDeclarationSpecifiersOrCo<wbr>nceptDefinition(DS, ParsedTemplateInfo(), AS,<br>
DeclSpecContext::DSC_top_<wbr>level);<br>
<br>
// If we had a free-standing type definition with a missing semicolon, we<br>
@@ -1287,7 +1287,7 @@ void Parser::<wbr>ParseKNRParamDeclarations(D<br>
<br>
// Parse the common declaration-specifiers piece.<br>
DeclSpec DS(AttrFactory);<br>
- ParseDeclarationSpecifiers(DS)<wbr>;<br>
+ ParseDeclarationSpecifiersOrCo<wbr>nceptDefinition(DS);<br>
<br>
// C99 6.9.1p6: 'each declaration in the declaration list shall have at<br>
// least one declarator'.<br>
@@ -1647,7 +1647,7 @@ bool Parser::<wbr>TryKeywordIdentFallback(boo<br>
/// Actions.getTypeName will not be needed to be called again (e.g. getTypeName<br>
/// will not be called twice, once to check whether we have a declaration<br>
/// specifier, and another one to get the actual type inside<br>
-/// ParseDeclarationSpecifiers).<br>
+/// ParseDeclarationSpecifiersOrCo<wbr>nceptDefinition).<br>
///<br>
/// This returns true if an error occurred.<br>
///<br>
<br>
Modified: cfe/trunk/lib/Sema/DeclSpec.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/DeclSpec.cpp?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>DeclSpec.cpp?rev=330794&r1=<wbr>330793&r2=330794&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Sema/DeclSpec.<wbr>cpp (original)<br>
+++ cfe/trunk/lib/Sema/DeclSpec.<wbr>cpp Tue Apr 24 19:42:26 2018<br>
@@ -426,6 +426,7 @@ unsigned DeclSpec::getParsedSpecifiers(<wbr>)<br>
return Res;<br>
}<br>
<br>
+<br>
template <class T> static bool BadSpecifier(T TNew, T TPrev,<br>
const char *&PrevSpec,<br>
unsigned &DiagID,<br>
@@ -491,7 +492,6 @@ const char *DeclSpec::getSpecifierName(T<br>
}<br>
llvm_unreachable("Unknown typespec!");<br>
}<br>
-<br>
const char *DeclSpec::getSpecifierName(<wbr>DeclSpec::TST T,<br>
const PrintingPolicy &Policy) {<br>
switch (T) {<br>
@@ -969,6 +969,69 @@ bool DeclSpec::SetConstexprSpec(<wbr>SourceLo<br>
return false;<br>
}<br>
<br>
+bool DeclSpec::setConceptSpec(const SourceLocation Loc, const char *&PrevSpec,<br>
+ unsigned &DiagID, const PrintingPolicy &PP) {<br>
+ assert(Loc.isValid() && "Loc must be valid, since it is used to identify "<br>
+ "that this function was called before");<br>
+ assert(!ConceptLoc.isValid() &&<br>
+ "how is this called if concept was already encountered and triggered "<br>
+ "ParseConceptDefinition which parses upto the semi-colon");<br>
+<br>
+ PrevSpec = nullptr;<br>
+ if (TypeSpecType != TST_unspecified) {<br>
+ PrevSpec = DeclSpec::getSpecifierName(<wbr>static_cast<TST>(TypeSpecType)<wbr>, PP);<br>
+ ClearTypeSpecType();<br>
+ }<br>
+ if (TypeSpecSign != TSS_unspecified) {<br>
+ PrevSpec = DeclSpec::getSpecifierName(<wbr>static_cast<TSS>(TypeSpecSign)<wbr>);<br>
+ TypeSpecSign = TSS_unspecified;<br>
+ }<br>
+ if (TypeSpecWidth != TSW_unspecified) {<br>
+ PrevSpec = DeclSpec::getSpecifierName(<wbr>static_cast<TSW>(<wbr>TypeSpecWidth));<br>
+ TypeSpecWidth = TSW_unspecified;<br>
+ }<br>
+ if (StorageClassSpec != SCS_unspecified) {<br>
+ PrevSpec = DeclSpec::getSpecifierName(<wbr>static_cast<SCS>(<wbr>StorageClassSpec));<br>
+ ClearStorageClassSpecs();<br>
+ }<br>
+ if (ThreadStorageClassSpec != TSCS_unspecified) {<br>
+ PrevSpec =<br>
+ DeclSpec::getSpecifierName(<wbr>static_cast<TSCS>(<wbr>ThreadStorageClassSpec));<br>
+ ClearStorageClassSpecs();<br>
+ }<br>
+ if (TypeSpecComplex != TSC_unspecified) {<br>
+ PrevSpec = DeclSpec::getSpecifierName(<wbr>static_cast<TSC>(<wbr>TypeSpecComplex));<br>
+ TypeSpecComplex = TSC_unspecified;<br>
+ }<br>
+ if (getTypeQualifiers()) {<br>
+ PrevSpec = DeclSpec::getSpecifierName(<wbr>static_cast<TQ>(<wbr>TypeQualifiers));<br>
+ ClearTypeQualifiers();<br>
+ }<br>
+ if (isFriendSpecified()) {<br>
+ PrevSpec = "friend";<br>
+ Friend_specified = false;<br>
+ FriendLoc = SourceLocation();<br>
+ }<br>
+ if (isConstexprSpecified()) {<br>
+ PrevSpec = "constexpr";<br>
+ Constexpr_specified = false;<br>
+ ConstexprLoc = SourceLocation();<br>
+ }<br>
+ if (isInlineSpecified()) {<br>
+ PrevSpec = "inline";<br>
+ FS_inlineLoc = SourceLocation();<br>
+ FS_inline_specified = false;<br>
+ }<br>
+<br>
+ if (PrevSpec) {<br>
+ DiagID = diag::err_invalid_decl_spec_<wbr>combination;<br>
+ }<br>
+ // We set the concept location regardless of whether an error occurred.<br>
+ DeclRep = nullptr;<br>
+ ConceptLoc = Loc;<br>
+ return PrevSpec; // If this is non-null, an error occurred.<br>
+}<br>
+<br>
void DeclSpec::<wbr>SaveWrittenBuiltinSpecs() {<br>
writtenBS.Sign = getTypeSpecSign();<br>
writtenBS.Width = getTypeSpecWidth();<br>
@@ -1270,6 +1333,7 @@ void DeclSpec::Finish(Sema &S, const Pri<br>
// TODO: return "auto function" and other bad things based on the real type.<br>
<br>
// 'data definition has no type or storage class'?<br>
+<br>
}<br>
<br>
bool DeclSpec::<wbr>isMissingDeclaratorOk() {<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaDecl.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaDecl.cpp?rev=330794&r1=<wbr>330793&r2=330794&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Sema/SemaDecl.<wbr>cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaDecl.<wbr>cpp Tue Apr 24 19:42:26 2018<br>
@@ -4212,6 +4212,12 @@ Sema::<wbr>ParsedFreeStandingDeclSpec(<wbr>Scope *<br>
MultiTemplateParamsArg TemplateParams,<br>
bool IsExplicitInstantiation,<br>
RecordDecl *&AnonRecord) {<br>
+<br>
+ // We don't need to do any additional declspecifier checking on concept<br>
+ // definitions since that should already have been done when the concept kw<br>
+ // location was set within DS.<br>
+ if (DS.isConceptSpecified()) return DS.getRepAsConcept();<br>
+ <br>
Decl *TagD = nullptr;<br>
TagDecl *Tag = nullptr;<br>
if (DS.getTypeSpecType() == DeclSpec::TST_class ||<br>
<br>
Modified: cfe/trunk/lib/Sema/<wbr>SemaDeclCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaDeclCXX.cpp?rev=330794&r1=<wbr>330793&r2=330794&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Sema/<wbr>SemaDeclCXX.cpp (original)<br>
+++ cfe/trunk/lib/Sema/<wbr>SemaDeclCXX.cpp Tue Apr 24 19:42:26 2018<br>
@@ -9467,7 +9467,7 @@ UsingShadowDecl *Sema::BuildUsingShadowD<br>
NonTemplateTarget = TargetTD->getTemplatedDecl();<br>
<br>
UsingShadowDecl *Shadow;<br>
- if (isa<CXXConstructorDecl>(<wbr>NonTemplateTarget)) {<br>
+ if (!isa<ConceptDecl>(Target) && isa<CXXConstructorDecl>(<wbr>NonTemplateTarget)) {<br>
bool IsVirtualBase =<br>
isVirtualDirectBase(cast<<wbr>CXXRecordDecl>(CurContext),<br>
UD->getQualifier()-><wbr>getAsRecordDecl());<br>
<br>
Modified: cfe/trunk/lib/Sema/<wbr>SemaTemplate.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaTemplate.cpp?rev=330794&<wbr>r1=330793&r2=330794&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Sema/<wbr>SemaTemplate.cpp (original)<br>
+++ cfe/trunk/lib/Sema/<wbr>SemaTemplate.cpp Tue Apr 24 19:42:26 2018<br>
@@ -232,9 +232,11 @@ TemplateNameKind Sema::isTemplateName(Sc<br>
} else {<br>
assert(isa<ClassTemplateDecl>(<wbr>TD) || isa<TemplateTemplateParmDecl>(<wbr>TD) ||<br>
isa<TypeAliasTemplateDecl>(TD) || isa<VarTemplateDecl>(TD) ||<br>
- isa<BuiltinTemplateDecl>(TD));<br>
+ isa<BuiltinTemplateDecl>(TD) || isa<ConceptDecl>(TD));<br>
TemplateKind =<br>
- isa<VarTemplateDecl>(TD) ? TNK_Var_template : TNK_Type_template;<br>
+ isa<VarTemplateDecl>(TD) ? TNK_Var_template :<br>
+ isa<ConceptDecl>(TD) ? TNK_Concept_template :<br>
+ TNK_Type_template;<br>
}<br>
}<br>
<br>
@@ -3034,7 +3036,8 @@ QualType Sema::CheckTemplateIdType(<wbr>Templ<br>
<br>
TemplateDecl *Template = Name.getAsTemplateDecl();<br>
if (!Template || isa<FunctionTemplateDecl>(<wbr>Template) ||<br>
- isa<VarTemplateDecl>(Template)<wbr>) {<br>
+ isa<VarTemplateDecl>(Template) ||<br>
+ isa<ConceptDecl>(Template)) {<br>
// We might have a substituted template template parameter pack. If so,<br>
// build a template specialization type for it.<br>
if (Name.<wbr>getAsSubstTemplateTemplateParm<wbr>Pack())<br>
@@ -3988,6 +3991,18 @@ Sema::CheckVarTemplateId(const CXXScopeS<br>
/*FoundD=*/nullptr, TemplateArgs);<br>
}<br>
<br>
+ExprResult<br>
+Sema::CheckConceptTemplateId(<wbr>const CXXScopeSpec &SS,<br>
+ const DeclarationNameInfo &NameInfo,<br>
+ ConceptDecl *Template,<br>
+ SourceLocation TemplateLoc,<br>
+ const TemplateArgumentListInfo *TemplateArgs) {<br>
+ // TODO: Do concept specialization here.<br>
+ Diag(Template->getLocation(), diag::err_concept_feature_<wbr>unimplemented)<br>
+ << "can not form concept template-id";<br>
+ return ExprError();<br>
+}<br>
+<br>
ExprResult Sema::BuildTemplateIdExpr(<wbr>const CXXScopeSpec &SS,<br>
SourceLocation TemplateKWLoc,<br>
LookupResult &R,<br>
@@ -4009,14 +4024,21 @@ ExprResult Sema::BuildTemplateIdExpr(con<br>
<br>
// In C++1y, check variable template ids.<br>
bool InstantiationDependent;<br>
- if (R.getAsSingle<<wbr>VarTemplateDecl>() &&<br>
- !TemplateSpecializationType::<wbr>anyDependentTemplateArguments(<br>
- *TemplateArgs, InstantiationDependent)) {<br>
+ const bool DependentArguments =<br>
+ TemplateSpecializationType::<wbr>anyDependentTemplateArguments(<br>
+ *TemplateArgs, InstantiationDependent);<br>
+ if (R.getAsSingle<<wbr>VarTemplateDecl>() && !DependentArguments) {<br>
return CheckVarTemplateId(SS, R.getLookupNameInfo(),<br>
R.getAsSingle<VarTemplateDecl><wbr>(),<br>
TemplateKWLoc, TemplateArgs);<br>
}<br>
<br>
+ if (R.getAsSingle<ConceptDecl>() && !DependentArguments) {<br>
+ return CheckConceptTemplateId(SS, R.getLookupNameInfo(),<br>
+ R.getAsSingle<ConceptDecl>(),<br>
+ TemplateKWLoc, TemplateArgs);<br>
+ }<br>
+<br>
// We don't want lookup warnings at this point.<br>
R.suppressDiagnostics();<br>
<br>
@@ -7688,6 +7710,61 @@ Decl *Sema::<wbr>ActOnTemplateDeclarator(Scop<br>
return NewDecl;<br>
}<br>
<br>
+ConceptDecl *Sema::ActOnConceptDefinition(<wbr>Scope *S,<br>
+ MultiTemplateParamsArg TemplateParameterLists, IdentifierInfo *Name,<br>
+ SourceLocation NameLoc, Expr *ConstraintExpr) {<br>
+ // C++2a [temp.concept]p3:<br>
+ // A concept-definition shall appear in the global scope or in a namespace<br>
+ // scope.<br>
+ assert(<br>
+ CurContext->isFileContext() &&<br>
+ "We check during parsing that 'concept's only occur at namespace scope");<br>
+<br>
+ // Forbid any prior declaration of this name within the current namespace.<br>
+ LookupResult Previous(*this,<br>
+ DeclarationNameInfo(<wbr>DeclarationName(Name), NameLoc),<br>
+ LookupOrdinaryName);<br>
+ LookupName(Previous, S);<br>
+ if (!Previous.empty()) {<br>
+ const NamedDecl *PrevDecl = Previous.<wbr>getRepresentativeDecl();<br>
+ if (PrevDecl->getDeclContext()-><wbr>Equals(CurContext)) {<br>
+ if (Previous.isSingleResult() &&<br>
+ isa<ConceptDecl>(Previous.<wbr>getFoundDecl())) {<br>
+ Diag(NameLoc, diag::err_redefinition) << Name;<br>
+ } else {<br>
+ Diag(NameLoc, diag::err_redefinition_<wbr>different_kind) << Name;<br>
+ }<br>
+ Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl;<br>
+ return nullptr;<br>
+ }<br>
+ }<br>
+<br>
+ ConceptDecl *NewDecl = ConceptDecl::Create(Context, CurContext, NameLoc,<br>
+ Name, TemplateParameterLists[0],<br>
+ ConstraintExpr);<br>
+<br>
+ if (!NewDecl)<br>
+ return nullptr;<br>
+<br>
+ if (NewDecl-><wbr>getAssociatedConstraints()) {<br>
+ // C++2a [temp.concept]p4:<br>
+ // A concept shall not have associated constraints.<br>
+ // TODO: Make a test once we have actual associated constraints.<br>
+ Diag(NameLoc, diag::err_concept_no_<wbr>associated_constraints);<br>
+ NewDecl->setInvalidDecl();<br>
+ }<br>
+<br>
+ assert((S-><wbr>isTemplateParamScope() || !TemplateParameterLists[0]-><wbr>size()) &&<br>
+ "Not in template param scope?");<br>
+ assert(S->getParent() && !S->getParent()-><wbr>isTemplateParamScope() &&<br>
+ "Parent scope should exist and not be template parameter.");<br>
+<br>
+ ActOnDocumentableDecl(NewDecl)<wbr>;<br>
+ PushOnScopeChains(NewDecl, S->getParent(), /*AddToContext=*/true);<br>
+<br>
+ return NewDecl;<br>
+}<br>
+<br>
/// \brief Strips various properties off an implicit instantiation<br>
/// that has just been explicitly specialized.<br>
static void StripImplicitInstantiation(<wbr>NamedDecl *D) {<br>
<br>
Modified: cfe/trunk/lib/Sema/<wbr>SemaTemplateInstantiateDecl.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaTemplateInstantiateDecl.<wbr>cpp?rev=330794&r1=330793&r2=<wbr>330794&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Sema/<wbr>SemaTemplateInstantiateDecl.<wbr>cpp (original)<br>
+++ cfe/trunk/lib/Sema/<wbr>SemaTemplateInstantiateDecl.<wbr>cpp Tue Apr 24 19:42:26 2018<br>
@@ -3073,6 +3073,11 @@ Decl *TemplateDeclInstantiator::<wbr>VisitFri<br>
return nullptr;<br>
}<br>
<br>
+Decl *TemplateDeclInstantiator::<wbr>VisitConceptDecl(ConceptDecl *D) {<br>
+ llvm_unreachable("Concept definitions cannot reside inside a template");<br>
+ return nullptr;<br>
+}<br>
+<br>
Decl *TemplateDeclInstantiator::<wbr>VisitDecl(Decl *D) {<br>
llvm_unreachable("Unexpected decl");<br>
}<br>
<br>
Modified: cfe/trunk/lib/Serialization/<wbr>ASTCommon.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTCommon.cpp?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/<wbr>Serialization/ASTCommon.cpp?<wbr>rev=330794&r1=330793&r2=<wbr>330794&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Serialization/<wbr>ASTCommon.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/<wbr>ASTCommon.cpp Tue Apr 24 19:42:26 2018<br>
@@ -313,6 +313,7 @@ bool serialization::<wbr>isRedeclarableDeclKi<br>
case Decl::BuiltinTemplate:<br>
case Decl::Decomposition:<br>
case Decl::Binding:<br>
+ case Decl::Concept:<br>
return false;<br>
<br>
// These indirectly derive from Redeclarable<T> but are not actually<br>
<br>
Modified: cfe/trunk/lib/Serialization/<wbr>ASTReaderDecl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/<wbr>Serialization/ASTReaderDecl.<wbr>cpp?rev=330794&r1=330793&r2=<wbr>330794&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Serialization/<wbr>ASTReaderDecl.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/<wbr>ASTReaderDecl.cpp Tue Apr 24 19:42:26 2018<br>
@@ -381,6 +381,7 @@ namespace clang {<br>
void VisitBindingDecl(BindingDecl *BD);<br>
void VisitNonTypeTemplateParmDecl(<wbr>NonTypeTemplateParmDecl *D);<br>
DeclID VisitTemplateDecl(TemplateDecl *D);<br>
+ void VisitConceptDecl(ConceptDecl *D);<br>
RedeclarableResult VisitRedeclarableTemplateDecl(<wbr>RedeclarableTemplateDecl *D);<br>
void VisitClassTemplateDecl(<wbr>ClassTemplateDecl *D);<br>
void VisitBuiltinTemplateDecl(<wbr>BuiltinTemplateDecl *D);<br>
@@ -2031,6 +2032,11 @@ DeclID ASTDeclReader::<wbr>VisitTemplateDecl(<br>
return PatternID;<br>
}<br>
<br>
+void ASTDeclReader::<wbr>VisitConceptDecl(ConceptDecl *D) {<br>
+ VisitTemplateDecl(D);<br>
+ D->setConstraintExpr(Record.<wbr>readExpr());<br>
+}<br>
+<br>
ASTDeclReader::<wbr>RedeclarableResult<br>
ASTDeclReader::<wbr>VisitRedeclarableTemplateDecl(<wbr>RedeclarableTemplateDecl *D) {<br>
RedeclarableResult Redecl = VisitRedeclarable(D);<br>
@@ -3595,6 +3601,9 @@ Decl *ASTReader::ReadDeclRecord(<wbr>DeclID I<br>
case DECL_TYPE_ALIAS_TEMPLATE:<br>
D = TypeAliasTemplateDecl::<wbr>CreateDeserialized(Context, ID);<br>
break;<br>
+ case DECL_CONCEPT:<br>
+ D = ConceptDecl::<wbr>CreateDeserialized(Context, ID);<br>
+ break;<br>
case DECL_STATIC_ASSERT:<br>
D = StaticAssertDecl::<wbr>CreateDeserialized(Context, ID);<br>
break;<br>
<br>
Modified: cfe/trunk/lib/Serialization/<wbr>ASTWriter.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/<wbr>Serialization/ASTWriter.cpp?<wbr>rev=330794&r1=330793&r2=<wbr>330794&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Serialization/<wbr>ASTWriter.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/<wbr>ASTWriter.cpp Tue Apr 24 19:42:26 2018<br>
@@ -1280,6 +1280,7 @@ void ASTWriter::<wbr>WriteBlockInfoBlock() {<br>
RECORD(DECL_TEMPLATE_TYPE_<wbr>PARM);<br>
RECORD(DECL_NON_TYPE_TEMPLATE_<wbr>PARM);<br>
RECORD(DECL_TEMPLATE_TEMPLATE_<wbr>PARM);<br>
+ RECORD(DECL_CONCEPT);<br>
RECORD(DECL_TYPE_ALIAS_<wbr>TEMPLATE);<br>
RECORD(DECL_STATIC_ASSERT);<br>
RECORD(DECL_CXX_BASE_<wbr>SPECIFIERS);<br>
<br>
Modified: cfe/trunk/lib/Serialization/<wbr>ASTWriterDecl.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/<wbr>Serialization/ASTWriterDecl.<wbr>cpp?rev=330794&r1=330793&r2=<wbr>330794&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Serialization/<wbr>ASTWriterDecl.cpp (original)<br>
+++ cfe/trunk/lib/Serialization/<wbr>ASTWriterDecl.cpp Tue Apr 24 19:42:26 2018<br>
@@ -102,6 +102,7 @@ namespace clang {<br>
void VisitBindingDecl(BindingDecl *D);<br>
void VisitNonTypeTemplateParmDecl(<wbr>NonTypeTemplateParmDecl *D);<br>
void VisitTemplateDecl(TemplateDecl *D);<br>
+ void VisitConceptDecl(ConceptDecl *D);<br>
void VisitRedeclarableTemplateDecl(<wbr>RedeclarableTemplateDecl *D);<br>
void VisitClassTemplateDecl(<wbr>ClassTemplateDecl *D);<br>
void VisitVarTemplateDecl(<wbr>VarTemplateDecl *D);<br>
@@ -1395,6 +1396,12 @@ void ASTDeclWriter::<wbr>VisitTemplateDecl(Te<br>
Record.<wbr>AddTemplateParameterList(D-><wbr>getTemplateParameters());<br>
}<br>
<br>
+void ASTDeclWriter::<wbr>VisitConceptDecl(ConceptDecl *D) {<br>
+ VisitTemplateDecl(D);<br>
+ Record.AddStmt(D-><wbr>getConstraintExpr());<br>
+ Code = serialization::DECL_CONCEPT;<br>
+}<br>
+<br>
void ASTDeclWriter::<wbr>VisitRedeclarableTemplateDecl(<wbr>RedeclarableTemplateDecl *D) {<br>
VisitRedeclarable(D);<br>
<br>
<br>
Removed: cfe/trunk/test/Parser/cxx-<wbr>concept-declaration.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx-concept-declaration.cpp?rev=330793&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/Parser/<wbr>cxx-concept-declaration.cpp?<wbr>rev=330793&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/Parser/cxx-<wbr>concept-declaration.cpp (original)<br>
+++ cfe/trunk/test/Parser/cxx-<wbr>concept-declaration.cpp (removed)<br>
@@ -1,7 +0,0 @@<br>
-<br>
-// Support parsing of concepts<br>
-// Disabled for now.<br>
-// expected-no-diagnostics<br>
-<br>
-// RUN: %clang_cc1 -std=c++14 -fconcepts-ts -x c++ -verify %s<br>
-// template<typename T> concept C1 = true;<br>
<br>
Added: cfe/trunk/test/Parser/cxx2a-<wbr>concept-declaration.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx2a-concept-declaration.cpp?rev=330794&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/Parser/<wbr>cxx2a-concept-declaration.cpp?<wbr>rev=330794&view=auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/Parser/cxx2a-<wbr>concept-declaration.cpp (added)<br>
+++ cfe/trunk/test/Parser/cxx2a-<wbr>concept-declaration.cpp Tue Apr 24 19:42:26 2018<br>
@@ -0,0 +1,83 @@<br>
+// RUN: %clang_cc1 -std=c++2a -fconcepts-ts -verify %s<br>
+// Support parsing of concepts<br>
+<br>
+concept X; //expected-error {{must be a template}}<br>
+<br>
+template<typename T> concept C1 = true; //expected-note{{declared here}} <-- previous declaration<br>
+<br>
+template<typename T> concept C1 = true; // expected-error {{redefinition of 'C1'}}<br>
+<br>
+template<concept T> concept D1 = true; // expected-error {{'concept' can only appear in namespace scope}} \<br>
+ expected-error {{expected template parameter}}<br>
+<br>
+template<> concept X = true; // expected-error {{cannot be explicitly specialized}}<br>
+<br>
+namespace ns1 {<br>
+template<> concept D1 = true; // expected-error {{cannot be explicitly specialized}}<br>
+template<typename T> const concept C1 = true; //expected-error{{cannot combine with}}<br>
+namespace ns12 {<br>
+template<typename T> decltype(T{}) concept C2 = true; //expected-error{{cannot combine with}}<br>
+template<typename T> bool concept C3 = true; //expected-error{{cannot combine with}}<br>
+template<typename T> unsigned concept C4 = true; //expected-error{{cannot combine with}}<br>
+template<typename T> short concept C5 = true; //expected-error{{cannot combine with}}<br>
+template<typename T> typedef concept C6 = true; //expected-error{{cannot combine with}}<br>
+}<br>
+template<class> concept <br>
+ const //expected-error{{expected concept name}}<br>
+ C2 = true; <br>
+ <br>
+void f() {<br>
+ concept X; //expected-error{{'concept' can only appear in namespace scope}}<br>
+}<br>
+template<concept X, //expected-error{{'concept' can only appear in namespace scope}} \<br>
+ expected-error {{expected template parameter}}<br>
+ int J> void f();<br>
+}<br>
+<br>
+template<class T><br>
+concept [[test]] X2 [[test2]] = T::value; //expected-error2{{attribute list cannot appear here}}<br>
+<br>
+namespace ns2 {<br>
+template<class T><br>
+concept [[test]] X2 [[test2]] = T::value; //expected-error2{{attribute list cannot appear here}}<br>
+ <br>
+}<br>
+<br>
+namespace ns3 {<br>
+ template<typename T> concept C1 = true; <br>
+<br>
+ namespace ns1 {<br>
+ using ns3::C1; //expected-note{{declared here}}<br>
+ template<typename T> concept C1 = true; // expected-error {{redefinition of 'C1'}}<br>
+ }<br>
+<br>
+}<br>
+<br>
+// TODO:<br>
+// template<typename T> concept C2 = 0.f; // expected error {{constraint expression must be 'bool'}}<br>
+<br>
+struct S1 {<br>
+ template<typename T> concept C1 = true; // expected-error {{can only appear in namespace scope}}<br>
+};<br>
+<br>
+template<typename A><br>
+template<typename B><br>
+concept C4 = true; // expected-error {{extraneous template parameter list in concept definition}}<br>
+<br>
+template<typename T> concept C5 = true; // expected-note {{previous}} expected-note {{previous}}<br>
+int C5; // expected-error {{redefinition}}<br>
+struct C5 {}; // expected-error {{redefinition}}<br>
+<br>
+struct C6 {}; //expected-note{{declared here}} <-- previous declaration<br>
+template<typename T> concept C6 = true; // expected-error {{redefinition of 'C6' as different kind of symbol}}<br>
+<br>
+namespace thing {};<br>
+<br>
+template<typename T> concept thing::C7 = true; // expected-error {{concepts must be defined in their own namespace}}<br>
+<br>
+<br>
+namespace ns5 {<br>
+}<br>
+<br>
+// TODO: Add test to prevent explicit specialization, partial specialization<br>
+// and explicit instantiation of concepts.<br>
<br>
Modified: cfe/trunk/tools/libclang/<wbr>CIndex.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=330794&r1=330793&r2=330794&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/tools/<wbr>libclang/CIndex.cpp?rev=<wbr>330794&r1=330793&r2=330794&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/tools/libclang/<wbr>CIndex.cpp (original)<br>
+++ cfe/trunk/tools/libclang/<wbr>CIndex.cpp Tue Apr 24 19:42:26 2018<br>
@@ -6173,6 +6173,7 @@ CXCursor clang_getCursorDefinition(<wbr>CXCur<br>
case Decl::PragmaComment:<br>
case Decl::PragmaDetectMismatch:<br>
case Decl::UsingPack:<br>
+ case Decl::Concept:<br>
return C;<br>
<br>
// Declaration kinds that don't make any sense here, but are<br>
<br>
<br>
______________________________<wbr>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div></div>