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'