Index: include/clang/Sema/DeclSpec.h =================================================================== --- include/clang/Sema/DeclSpec.h +++ include/clang/Sema/DeclSpec.h @@ -357,6 +357,9 @@ // constexpr-specifier unsigned Constexpr_specified : 1; + // concept-specifier + unsigned Concept_specified : 1; + union { UnionParsedType TypeRep; Decl *DeclRep; @@ -392,7 +395,7 @@ SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc, TQ_atomicLoc; SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc, FS_noreturnLoc; SourceLocation FS_forceinlineLoc; - SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc; + SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc, ConceptLoc; WrittenBuiltinSpecs writtenBS; void SaveWrittenBuiltinSpecs(); @@ -436,6 +439,7 @@ FS_noreturn_specified(false), Friend_specified(false), Constexpr_specified(false), + Concept_specified(false), Attrs(attrFactory), ProtocolQualifiers(nullptr), NumProtocolQualifiers(0), @@ -687,6 +691,8 @@ unsigned &DiagID); bool SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID); + bool SetConceptSpec(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID); bool isFriendSpecified() const { return Friend_specified; } SourceLocation getFriendSpecLoc() const { return FriendLoc; } @@ -697,11 +703,19 @@ bool isConstexprSpecified() const { return Constexpr_specified; } SourceLocation getConstexprSpecLoc() const { return ConstexprLoc; } + bool isConceptSpecified() const { return Concept_specified; } + SourceLocation getConceptSpecLoc() const { return ConceptLoc; } + void ClearConstexprSpec() { Constexpr_specified = false; ConstexprLoc = SourceLocation(); } + void ClearConceptSpec() { + Concept_specified = false; + ConceptLoc = SourceLocation(); + } + AttributePool &getAttributePool() const { return Attrs.getPool(); } Index: lib/Parse/ParseDecl.cpp =================================================================== --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -3150,6 +3150,11 @@ isInvalid = DS.SetConstexprSpec(Loc, PrevSpec, DiagID); break; + // concept + case tok::kw_concept: + isInvalid = DS.SetConceptSpec(Loc, PrevSpec, DiagID); + break; + // type-specifier case tok::kw_short: isInvalid = DS.SetTypeSpecWidth(DeclSpec::TSW_short, Loc, PrevSpec, @@ -4429,6 +4434,9 @@ case tok::annot_decltype: case tok::kw_constexpr: + // C++ Concepts TS - concept + case tok::kw_concept: + // C11 _Atomic case tok::kw__Atomic: return true; Index: lib/Parse/ParseTentative.cpp =================================================================== --- lib/Parse/ParseTentative.cpp +++ lib/Parse/ParseTentative.cpp @@ -1211,9 +1211,11 @@ // 'friend' // 'typedef' // 'constexpr' + // 'concept' case tok::kw_friend: case tok::kw_typedef: case tok::kw_constexpr: + case tok::kw_concept: // storage-class-specifier case tok::kw_register: case tok::kw_static: Index: lib/Sema/DeclSpec.cpp =================================================================== --- lib/Sema/DeclSpec.cpp +++ lib/Sema/DeclSpec.cpp @@ -893,6 +893,18 @@ return false; } +bool DeclSpec::SetConceptSpec(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID) { + if (Concept_specified) { + DiagID = diag::ext_duplicate_declspec; + PrevSpec = "concept"; + return true; + } + Concept_specified = true; + ConceptLoc = Loc; + return false; +} + void DeclSpec::setProtocolQualifiers(Decl * const *Protos, unsigned NP, SourceLocation *ProtoLocs, Index: test/Parser/cxx-concept-declaration.cpp =================================================================== --- /dev/null +++ test/Parser/cxx-concept-declaration.cpp @@ -0,0 +1,30 @@ + +// Support parsing of function concepts and variable concepts + +// RUN: %clang_cc1 -std=c++14 -fconcepts-ts -x c++ -verify %s + +template concept bool C1 = true; + +template concept bool C2() { return true; } + +template +struct A { typedef bool Boolean; }; + +template +A::Boolean concept C3(!0); + +template +concept auto C4(void) -> bool { return true; } + +constexpr int One = 1; + +template +static concept decltype(!0) C5 { bool(One) }; + +template concept concept bool C6 = true; // expected-warning {{duplicate 'concept' declaration specifier}} + +template concept concept bool C7() { return true; } // expected-warning {{duplicate 'concept' declaration specifier}} + +concept D1 = true; // expected-error {{C++ requires a type specifier for all declarations}} + +template concept bool D2 = true; // expected-error {{unknown type name 'T'}}