r330794 - [c++2a] [concepts] Add rudimentary parsing support for template concept declarations

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 25 14:12:00 PDT 2018


On 25 April 2018 at 13:59, Faisal Vali via cfe-commits <
cfe-commits at lists.llvm.org> wrote:

> On Wed, Apr 25, 2018 at 3:37 PM, Richard Smith <richard at metafoo.co.uk>
> wrote:
> > On 24 April 2018 at 19:42, Faisal Vali via cfe-commits
> > <cfe-commits at lists.llvm.org> wrote:
> >>
> >> Author: faisalv
> >> Date: Tue Apr 24 19:42:26 2018
> >> New Revision: 330794
> >>
> >> URL: http://llvm.org/viewvc/llvm-project?rev=330794&view=rev
> >> Log:
> >> [c++2a] [concepts] Add rudimentary parsing support for template concept
> >> declarations
> >>
> >>
> >> This patch is a tweak of changyu's patch: https://reviews.llvm.org/
> D40381.
> >> 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.
> >
> >
> > 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).
> >
>
> I wouldn't say that I'm certain it's worth it - but then it also
> didn't seem to me that the complexity tax being paid was that high
> (but probably because my bias leans towards overly-diagnosticating for
> users who are still learning the syntax of the language - and i can
> imagine folks trying to add types to concept declarations or
> attributes - which we may choose to allow in the future..)
>
> Eitherway - I really don't feel strongly about this - just felt it
> might be a better service to provide our users - but I do see your
> point and the coherence concerns regarding our structure and since you
> do feel strongly about it, i'll replace it with changyu's approach.
>

Thanks!

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.


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


More information about the cfe-commits mailing list