<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On 25 April 2018 at 13:59, 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"><span class="">On Wed, Apr 25, 2018 at 3:37 PM, Richard Smith <<a href="mailto:richard@metafoo.co.uk">richard@metafoo.co.uk</a>> wrote:<br>
> On 24 April 2018 at 19:42, Faisal Vali via cfe-commits<br>
> <<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a>> wrote:<br>
>><br>
>> 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<br>
>> 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>.<br>
>> It differs in that the recognition of the 'concept' token is moved into the<br>
>> machinery that recognizes declaration-specifiers - this allows us to<br>
>> leverage the attribute handling machinery more seamlessly.<br>
><br>
><br>
> Is that really worth it? This seems to add complexity to decl-specifier-seq<br>
> / declarator parsing for a construct that has nothing to do with those<br>
> things. I prefer the simpler approach in changyu's patch. I don't think the<br>
> diagnostics you're producing are worthwhile -- the problem is not that<br>
> "concept" can't be combined with other specifiers, it's that it's a<br>
> fundamentally different kind of construct (just like "using X = ...", which<br>
> it's much more like than it is like a declarator declaration).<br>
><br>
<br>
</span>I wouldn't say that I'm certain it's worth it - but then it also<br>
didn't seem to me that the complexity tax being paid was that high<br>
(but probably because my bias leans towards overly-diagnosticating for<br>
users who are still learning the syntax of the language - and i can<br>
imagine folks trying to add types to concept declarations or<br>
attributes - which we may choose to allow in the future..)<br>
<br>
Eitherway - I really don't feel strongly about this - just felt it<br>
might be a better service to provide our users - but I do see your<br>
point and the coherence concerns regarding our structure and since you<br>
do feel strongly about it, i'll replace it with changyu's approach.<br></blockquote><div><br></div><div>Thanks!</div><div><br></div><div>I think it is worth checking for (and maybe even accepting as an extension) a single 'bool' token after 'concept', because the Concepts TS allowed / required that. But I think the complexity of (for example) extending DeclSpec to contain 'concept' is not worthwhile.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Sorry about that and thanks for the feedback!<br>
<div class="HOEnZb"><div class="h5"><br>
<br>
>> See the test file to get a sense of the basic parsing that this patch<br>
>> 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:<br>
>> <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>
>><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<br>
>> 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>
>> }<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:<br>
>> <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>
>><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<br>
>> 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>
>> +<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<br>
>> 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:<br>
>> <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>
>><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:<br>
>> <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>
>><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<br>
>> 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<br>
>> namespace">;<br>
>> +def err_concept_nontemplate : Error<"concept definition must be a<br>
>> 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:<br>
>> <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>
>><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<br>
>> 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<br>
>> 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<br>
>> specialization}0">;<br>
>> -def err_concept_specialized : Error<<br>
>> -  "%select{function|variable}0 concept cannot be "<br>
>> -  "%select{explicitly instantiated|explicitly specialized|partially<br>
>> 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:<br>
>> <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>
>><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<br>
>> 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:<br>
>> <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>
>><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 ';'<br>
>> emitting<br>
>> +  /// diagnostics as necessary and storing parsed information within DS.<br>
>> +  ///<br>
>> +  /// Note: Asides from parsing the routine C/C++ decl-specifiers (which<br>
>> could<br>
>> +  /// include entire class or enum definitions), this also parses a<br>
>> 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<br>
>> [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>
>><br>
>> //===-------------------------<wbr>------------------------------<wbr>-------------===//<br>
>>    // Modules<br>
>>    DeclGroupPtrTy ParseModuleDecl();<br>
>><br>
>> Modified: cfe/trunk/include/clang/Sema/<wbr>DeclSpec.h<br>
>> URL:<br>
>> <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>
>><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<br>
>> includes<br>
>> +/// class and enum definitions whose AST representations must be stored -<br>
>> 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<br>
>> type<br>
>> +    // specifier, this stores the AST representation.  This is valid if<br>
>> 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<br>
>> 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<br>
>> type");<br>
>>      return TypeRep;<br>
>> @@ -491,6 +509,17 @@ public:<br>
>>      assert(isDeclRep((TST) TypeSpecType) && "DeclSpec does not store a<br>
>> 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<br>
>> 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<br>
>> 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<br>
>> a<br>
>> +  // template so that ConceptDecl only has to be defined where this is<br>
>> 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<br>
>> 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:<br>
>> <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>
>><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<br>
>> &DS,<br>
>>                                     RecordDecl *&AnonRecord);<br>
>> +<br>
>>    Decl *ParsedFreeStandingDeclSpec(<wbr>Scope *S, AccessSpecifier AS, DeclSpec<br>
>> &DS,<br>
>>                                     MultiTemplateParamsArg TemplateParams,<br>
>>                                     bool IsExplicitInstantiation,<br>
>> @@ -6229,6 +6230,13 @@ public:<br>
>>                                  SourceLocation TemplateLoc,<br>
>>                                  const TemplateArgumentListInfo<br>
>> *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>
>><br>
>> //===-------------------------<wbr>------------------------------<wbr>-------------===//<br>
>>    // C++ Variadic Templates (C++0x [temp.variadic])<br>
>><br>
>> //===-------------------------<wbr>------------------------------<wbr>-------------===//<br>
>><br>
>> Modified: cfe/trunk/include/clang/<wbr>Serialization/ASTBitCodes.h<br>
>> URL:<br>
>> <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>
>><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<br>
>> 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:<br>
>> <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>
>><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>
>> {<br>
>>    // FIXME: We don't add a declaration of a function template<br>
>> specialization<br>
>>    // to its context when it's explicitly instantiated, so dump explicit<br>
>><br>
>> Modified: cfe/trunk/lib/AST/DeclBase.cpp<br>
>> URL:<br>
>> <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>
>><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<br>
>> 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:<br>
>> <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>
>><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>
>><br>
>> //===-------------------------<wbr>------------------------------<wbr>---------------===//<br>
>> +// ConceptDecl Implementation<br>
>><br>
>> +//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
>> +ConceptDecl *ConceptDecl::Create(<wbr>ASTContext &C, DeclContext *DC,<br>
>> +                                 SourceLocation NameLoc, DeclarationName<br>
>> 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,<br>
>> ConstraintExpr);<br>
>> +}<br>
>> +<br>
>> +ConceptDecl *ConceptDecl::<wbr>CreateDeserialized(ASTContext &C,<br>
>> +                                             unsigned ID) {<br>
>> +  ConceptDecl *Result = new (C, ID) ConceptDecl(nullptr,<br>
>> SourceLocation(),<br>
>> +                                                DeclarationName(),<br>
>> +                                                nullptr, nullptr);<br>
>> +<br>
>> +  return Result;<br>
>> +}<br>
>> +<br>
>><br>
>> +//===------------------------<wbr>------------------------------<wbr>----------------===//<br>
>>  // ClassTemplatePartialSpecializa<wbr>tionDecl Implementation<br>
>><br>
>> //===-------------------------<wbr>------------------------------<wbr>---------------===//<br>
>>  void ClassTemplatePartialSpecializa<wbr>tionDecl::anchor() {}<br>
>><br>
>> Modified: cfe/trunk/lib/CodeGen/CGDecl.<wbr>cpp<br>
>> URL:<br>
>> <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>
>><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:<br>
>> <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>
>><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:<br>
>> <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>
>><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 =<br>
>> getDeclSpecContextFromDeclarat<wbr>orContext(Context);<br>
>> -  ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none,<br>
>> DSContext);<br>
>> +  ParseDeclarationSpecifiersOrCo<wbr>nceptDefinition(DS, ParsedTemplateInfo(),<br>
>> +                                                       AS_none,<br>
>> DSContext);<br>
>><br>
>>    // If we had a free-standing type definition with a missing semicolon,<br>
>> 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.<br>
>> 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(),<br>
>> 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,<br>
>> 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<br>
>> &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,<br>
>> 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:<br>
>> <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>
>><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,<br>
>> DeclSpecContext::DSC_class,<br>
>> -                             &CommonLateParsedAttrs);<br>
>> +  ParseDeclarationSpecifiersOrCo<wbr>nceptDefinition(<br>
>> +      DS, TemplateInfo, AS, DeclSpecContext::DSC_class,<br>
>> &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:<br>
>> <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>
>><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:<br>
>> <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>
>><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 '>'<br>
>> 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() &<br>
>> ~Scope::TemplateParamScope;<br>
>>    ParseScopeFlags TemplateScopeFlags(this, NewFlags, isSpecialization);<br>
>><br>
>> -  // Parse the actual template declaration.<br>
>> -  return ParseSingleDeclarationAfterTem<wbr>plate(Context,<br>
>> -<br>
>> ParsedTemplateInfo(&<wbr>ParamLists,<br>
>> -<br>
>> isSpecialization,<br>
>> -<br>
>> LastParamListWasEmpty),<br>
>> -                                             ParsingTemplateParams,<br>
>> -                                             DeclEnd, AS, AccessAttrs);<br>
>> +  return ParseSingleDeclarationAfterTem<wbr>plate(<br>
>> +      Context,<br>
>> +      ParsedTemplateInfo(&<wbr>ParamLists, isSpecialization,<br>
>> 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>
>><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<br>
>> &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<br>
>> is<br>
>> +  // likely where they will go...).<br>
>> +  DiagnoseAttributes();<br>
>> +<br>
>> +  // Set the concept specifier at ConceptLoc within 'DS' along with<br>
>> 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<br>
>> ';'. 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)<br>
>> 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 =<br>
>> *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<br>
>> 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,<br>
>> 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<br>
>> token<br>
>> +    // to ';' so that the rest of the code recovers as though there were<br>
>> 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<br>
>> in<br>
>>  /// angle brackets. Depth is the depth of this template-parameter-list,<br>
>> which<br>
>>  /// is the number of template headers directly enclosing this template<br>
>> 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,<br>
>> 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:<br>
>> <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>
>><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:<br>
>> <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>
>><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(),<br>
>> AS,<br>
>>                               DeclSpecContext::DSC_top_<wbr>level);<br>
>><br>
>>    // If we had a free-standing type definition with a missing semicolon,<br>
>> 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<br>
>> 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.<br>
>> 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:<br>
>> <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>
>><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<br>
>> *&PrevSpec,<br>
>> +                              unsigned &DiagID, const PrintingPolicy &PP)<br>
>> {<br>
>> +  assert(Loc.isValid() && "Loc must be valid, since it is used to<br>
>> identify "<br>
>> +                          "that this function was called before");<br>
>> +  assert(!ConceptLoc.isValid() &&<br>
>> +         "how is this called if concept was already encountered and<br>
>> 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>,<br>
>> PP);<br>
>> +         ClearTypeSpecType();<br>
>> +  }<br>
>> +  if (TypeSpecSign != TSS_unspecified) {<br>
>> +    PrevSpec =<br>
>> DeclSpec::getSpecifierName(<wbr>static_cast<TSS>(TypeSpecSign)<wbr>);<br>
>> +         TypeSpecSign = TSS_unspecified;<br>
>> +  }<br>
>> +  if (TypeSpecWidth != TSW_unspecified) {<br>
>> +    PrevSpec =<br>
>> DeclSpec::getSpecifierName(<wbr>static_cast<TSW>(<wbr>TypeSpecWidth));<br>
>> +         TypeSpecWidth = TSW_unspecified;<br>
>> +  }<br>
>> +  if (StorageClassSpec != SCS_unspecified) {<br>
>> +    PrevSpec =<br>
>> DeclSpec::getSpecifierName(<wbr>static_cast<SCS>(<wbr>StorageClassSpec));<br>
>> +         ClearStorageClassSpecs();<br>
>> +  }<br>
>> +  if (ThreadStorageClassSpec != TSCS_unspecified) {<br>
>> +    PrevSpec =<br>
>> +<br>
>> DeclSpec::getSpecifierName(<wbr>static_cast<TSCS>(<wbr>ThreadStorageClassSpec));<br>
>> +    ClearStorageClassSpecs();<br>
>> +  }<br>
>> +  if (TypeSpecComplex != TSC_unspecified) {<br>
>> +    PrevSpec =<br>
>> DeclSpec::getSpecifierName(<wbr>static_cast<TSC>(<wbr>TypeSpecComplex));<br>
>> +    TypeSpecComplex = TSC_unspecified;<br>
>> +  }<br>
>> +  if (getTypeQualifiers()) {<br>
>> +         PrevSpec =<br>
>> 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<br>
>> 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:<br>
>> <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>
>><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<br>
>> 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:<br>
>> <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>
>><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) &&<br>
>> 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:<br>
>> <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>
>><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) ||<br>
>> isa<TemplateTemplateParmDecl>(<wbr>TD) ||<br>
>>               isa<TypeAliasTemplateDecl>(TD) || isa<VarTemplateDecl>(TD)<br>
>> ||<br>
>> -             isa<BuiltinTemplateDecl>(TD));<br>
>> +             isa<BuiltinTemplateDecl>(TD) || isa<ConceptDecl>(TD));<br>
>>        TemplateKind =<br>
>> -          isa<VarTemplateDecl>(TD) ? TNK_Var_template :<br>
>> 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<br>
>> 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<br>
>> *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<br>
>> namespace<br>
>> +  // scope.<br>
>> +  assert(<br>
>> +      CurContext->isFileContext() &&<br>
>> +      "We check during parsing that 'concept's only occur at namespace<br>
>> scope");<br>
>> +<br>
>> +  // Forbid any prior declaration of this name within the current<br>
>> namespace.<br>
>> +  LookupResult Previous(*this,<br>
>> +                        DeclarationNameInfo(<wbr>DeclarationName(Name),<br>
>> 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) <<<br>
>> PrevDecl;<br>
>> +      return nullptr;<br>
>> +    }<br>
>> +  }<br>
>> +<br>
>> +  ConceptDecl *NewDecl = ConceptDecl::Create(Context, CurContext,<br>
>> NameLoc,<br>
>> +                                             Name,<br>
>> 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() ||<br>
>> !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:<br>
>> <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>
>><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<br>
>> 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<br>
>> 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:<br>
>> <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>
>><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:<br>
>> <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>
>><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<br>
>> 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>
>> {<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:<br>
>> <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>
>><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:<br>
>> <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>
>><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<br>
>> ASTDeclWriter::<wbr>VisitRedeclarableTemplateDecl(<wbr>RedeclarableTemplateDecl *D) {<br>
>>    VisitRedeclarable(D);<br>
>><br>
>><br>
>> Removed: cfe/trunk/test/Parser/cxx-<wbr>concept-declaration.cpp<br>
>> URL:<br>
>> <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>
>><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:<br>
>> <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>
>><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<br>
>> 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}}<br>
>> <-- previous declaration<br>
>> +<br>
>> +template<typename T> concept C1 = true; // expected-error {{redefinition<br>
>> of 'C1'}}<br>
>> +<br>
>> +template<concept T> concept D1 = true; // expected-error {{'concept' can<br>
>> only appear in namespace scope}} \<br>
>> +                                          expected-error {{expected<br>
>> template parameter}}<br>
>> +<br>
>> +template<> concept X = true; // expected-error {{cannot be explicitly<br>
>> specialized}}<br>
>> +<br>
>> +namespace ns1 {<br>
>> +template<> concept D1 = true;  // expected-error {{cannot be explicitly<br>
>> specialized}}<br>
>> +template<typename T> const concept C1 = true; //expected-error{{cannot<br>
>> combine with}}<br>
>> +namespace ns12 {<br>
>> +template<typename T> decltype(T{}) concept C2 = true;<br>
>> //expected-error{{cannot combine with}}<br>
>> +template<typename T> bool concept C3 = true; //expected-error{{cannot<br>
>> combine with}}<br>
>> +template<typename T> unsigned concept C4 = true; //expected-error{{cannot<br>
>> combine with}}<br>
>> +template<typename T> short concept C5 = true; //expected-error{{cannot<br>
>> combine with}}<br>
>> +template<typename T> typedef concept C6 = true; //expected-error{{cannot<br>
>> 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<br>
>> namespace scope}}<br>
>> +}<br>
>> +template<concept X,  //expected-error{{'concept' can only appear in<br>
>> namespace scope}} \<br>
>> +                                          expected-error {{expected<br>
>> template parameter}}<br>
>> +                                 int J> void f();<br>
>> +}<br>
>> +<br>
>> +template<class T><br>
>> +concept [[test]] X2 [[test2]] = T::value; //expected-error2{{attribute<br>
>> list cannot appear here}}<br>
>> +<br>
>> +namespace ns2 {<br>
>> +template<class T><br>
>> +concept [[test]] X2 [[test2]] = T::value; //expected-error2{{attribute<br>
>> 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<br>
>> {{redefinition of 'C1'}}<br>
>> +  }<br>
>> +<br>
>> +}<br>
>> +<br>
>> +// TODO:<br>
>> +// template<typename T> concept C2 = 0.f; // expected error {{constraint<br>
>> expression must be 'bool'}}<br>
>> +<br>
>> +struct S1 {<br>
>> +  template<typename T> concept C1 = true; // expected-error {{can only<br>
>> appear in namespace scope}}<br>
>> +};<br>
>> +<br>
>> +template<typename A><br>
>> +template<typename B><br>
>> +concept C4 = true; // expected-error {{extraneous template parameter list<br>
>> in concept definition}}<br>
>> +<br>
>> +template<typename T> concept C5 = true; // expected-note {{previous}}<br>
>> 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<br>
>> of 'C6' as different kind of symbol}}<br>
>> +<br>
>> +namespace thing {};<br>
>> +<br>
>> +template<typename T> concept thing::C7 = true;  // expected-error<br>
>> {{concepts must be defined in their own namespace}}<br>
>> +<br>
>> +<br>
>> +namespace ns5 {<br>
>> +}<br>
>> +<br>
>> +// TODO: Add test to prevent explicit specialization, partial<br>
>> specialization<br>
>> +// and explicit instantiation of concepts.<br>
>><br>
>> Modified: cfe/trunk/tools/libclang/<wbr>CIndex.cpp<br>
>> URL:<br>
>> <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>
>><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>
><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>
</div></div></blockquote></div><br></div></div>