Change ParseOptionalCXX0XVirtSpecifierSeq to take a VirtSpecifiers struct.
Enforce C++[class.mem]p8:
A virt-specifier-seq shall contain at most one of each virt-specifier.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123611 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 960a9fa..8672987 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -1268,15 +1268,21 @@
/// override
/// final
/// new
-bool Parser::isCXX0XVirtSpecifier() const {
+VirtSpecifiers::VirtSpecifier Parser::isCXX0XVirtSpecifier() const {
if (Tok.is(tok::kw_new))
- return true;
+ return VirtSpecifiers::VS_New;
- if (Tok.isNot(tok::identifier))
- return false;
+ if (Tok.is(tok::identifier)) {
+ IdentifierInfo *II = Tok.getIdentifierInfo();
- const IdentifierInfo *II = Tok.getIdentifierInfo();
- return II == Ident_override || II == Ident_final;
+ if (II == Ident_override)
+ return VirtSpecifiers::VS_Override;
+
+ if (II == Ident_final)
+ return VirtSpecifiers::VS_Final;
+ }
+
+ return VirtSpecifiers::VS_None;
}
/// ParseOptionalCXX0XVirtSpecifierSeq - Parse a virt-specifier-seq.
@@ -1284,10 +1290,26 @@
/// virt-specifier-seq:
/// virt-specifier
/// virt-specifier-seq virt-specifier
-void Parser::ParseOptionalCXX0XVirtSpecifierSeq() {
+void Parser::ParseOptionalCXX0XVirtSpecifierSeq(VirtSpecifiers &VS) {
if (!getLang().CPlusPlus0x)
return;
+ while (true) {
+ VirtSpecifiers::VirtSpecifier Specifier = isCXX0XVirtSpecifier();
+ if (Specifier == VirtSpecifiers::VS_None)
+ return;
+
+ // C++ [class.mem]p8:
+ // A virt-specifier-seq shall contain at most one of each virt-specifier.
+ const char* PrevSpec = 0;
+ if (VS.SetVirtSpecifier(Specifier, Tok.getLocation(), PrevSpec))
+ Diag(Tok.getLocation(), diag::err_duplicate_virt_specifier)
+ << PrevSpec
+ << FixItHint::CreateRemoval(Tok.getLocation());
+
+ ConsumeToken();
+ }
+
while (isCXX0XVirtSpecifier()) {
// FIXME: Actually do something with the specifier.
ConsumeToken();
@@ -1512,7 +1534,8 @@
SkipUntil(tok::comma, true, true);
}
- ParseOptionalCXX0XVirtSpecifierSeq();
+ VirtSpecifiers VS;
+ ParseOptionalCXX0XVirtSpecifierSeq(VS);
// pure-specifier:
// '= 0'