summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Sema/DeclSpec.h16
-rw-r--r--clang/lib/Parse/ParseDecl.cpp8
-rw-r--r--clang/lib/Parse/ParseTentative.cpp2
-rw-r--r--clang/lib/Sema/DeclSpec.cpp12
-rw-r--r--clang/test/Parser/cxx-concept-declaration.cpp30
5 files changed, 67 insertions, 1 deletions
diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h
index 2ec3286ad79..d375ec30378 100644
--- a/clang/include/clang/Sema/DeclSpec.h
+++ b/clang/include/clang/Sema/DeclSpec.h
@@ -358,6 +358,9 @@ private:
// constexpr-specifier
unsigned Constexpr_specified : 1;
+ // concept-specifier
+ unsigned Concept_specified : 1;
+
union {
UnionParsedType TypeRep;
Decl *DeclRep;
@@ -393,7 +396,7 @@ private:
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();
@@ -437,6 +440,7 @@ public:
FS_noreturn_specified(false),
Friend_specified(false),
Constexpr_specified(false),
+ Concept_specified(false),
Attrs(attrFactory),
ProtocolQualifiers(nullptr),
NumProtocolQualifiers(0),
@@ -688,6 +692,8 @@ public:
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; }
@@ -698,11 +704,19 @@ public:
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();
}
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index f497c59cec1..d843e801b63 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -3192,6 +3192,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
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,
@@ -4475,6 +4480,9 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
case tok::annot_decltype:
case tok::kw_constexpr:
+ // C++ Concepts TS - concept
+ case tok::kw_concept:
+
// C11 _Atomic
case tok::kw__Atomic:
return true;
diff --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp
index 536e98c6831..368cb934bba 100644
--- a/clang/lib/Parse/ParseTentative.cpp
+++ b/clang/lib/Parse/ParseTentative.cpp
@@ -1213,9 +1213,11 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
// '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:
diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp
index 1e7fc750a9c..d5c8871cac8 100644
--- a/clang/lib/Sema/DeclSpec.cpp
+++ b/clang/lib/Sema/DeclSpec.cpp
@@ -893,6 +893,18 @@ bool DeclSpec::SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec,
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,
diff --git a/clang/test/Parser/cxx-concept-declaration.cpp b/clang/test/Parser/cxx-concept-declaration.cpp
new file mode 100644
index 00000000000..591629ca285
--- /dev/null
+++ b/clang/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<typename T> concept bool C1 = true;
+
+template<typename T> concept bool C2() { return true; }
+
+template<typename T>
+struct A { typedef bool Boolean; };
+
+template<int N>
+A<void>::Boolean concept C3(!0);
+
+template<typename T, int = 0>
+concept auto C4(void) -> bool { return true; }
+
+constexpr int One = 1;
+
+template <typename>
+static concept decltype(!0) C5 { bool(One) };
+
+template<typename T> concept concept bool C6 = true; // expected-warning {{duplicate 'concept' declaration specifier}}
+
+template<typename T> 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 T> concept bool D2 = true; // expected-error {{unknown type name 'T'}}
OpenPOWER on IntegriCloud