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