[cfe-commits] r124036 - in /cfe/trunk: include/clang/Basic/DiagnosticParseKinds.td include/clang/Parse/Parser.h include/clang/Sema/DeclSpec.h lib/Parse/ParseDeclCXX.cpp lib/Sema/DeclSpec.cpp test/CXX/class/p1-0x.cpp

Anders Carlsson andersca at mac.com
Sat Jan 22 08:56:46 PST 2011


Author: andersca
Date: Sat Jan 22 10:56:46 2011
New Revision: 124036

URL: http://llvm.org/viewvc/llvm-project?rev=124036&view=rev
Log:
Parse class-virt-specifier-seqs.

Added:
    cfe/trunk/test/CXX/class/p1-0x.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/include/clang/Sema/DeclSpec.h
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Sema/DeclSpec.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=124036&r1=124035&r2=124036&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Sat Jan 22 10:56:46 2011
@@ -392,6 +392,8 @@
 // C++0x override control
 def err_duplicate_virt_specifier : Error<
   "class member already marked '%0'">;
+def err_duplicate_class_virt_specifier : Error<
+  "class already marked '%0'">;
 
 def err_scoped_enum_missing_identifier : Error<
   "scoped enumeration requires a name">;

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=124036&r1=124035&r2=124036&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Sat Jan 22 10:56:46 2011
@@ -1528,9 +1528,12 @@
   
   ExprResult ParseCXX0XAlignArgument(SourceLocation Start);
 
-  VirtSpecifiers::VirtSpecifier isCXX0XVirtSpecifier() const;
+  VirtSpecifiers::Specifier isCXX0XVirtSpecifier() const;
   void ParseOptionalCXX0XVirtSpecifierSeq(VirtSpecifiers &VS);
 
+  ClassVirtSpecifiers::Specifier isCXX0XClassVirtSpecifier() const;
+  void ParseOptionalCXX0XClassVirtSpecifierSeq(ClassVirtSpecifiers &CVS);
+
   /// DeclaratorScopeObj - RAII object used in Parser::ParseDirectDeclarator to
   /// enter a new C++ declarator scope and exit it when the function is
   /// finished.

Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=124036&r1=124035&r2=124036&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Sema/DeclSpec.h Sat Jan 22 10:56:46 2011
@@ -1471,7 +1471,7 @@
 /// VirtSpecifiers - Represents a C++0x virt-specifier-seq.
 class VirtSpecifiers {
 public:
-  enum VirtSpecifier {
+  enum Specifier {
     VS_None = 0,
     VS_Override = 1,
     VS_Final = 2,
@@ -1480,7 +1480,7 @@
 
   VirtSpecifiers() : Specifiers(0) { }
 
-  bool SetSpecifier(VirtSpecifier VS, SourceLocation Loc,
+  bool SetSpecifier(Specifier VS, SourceLocation Loc,
                     const char *&PrevSpec);
 
   bool isOverrideSpecified() const { return Specifiers & VS_Override; }
@@ -1497,14 +1497,14 @@
 
   SourceLocation VS_overrideLoc, VS_finalLoc, VS_newLoc;
 
-  static const char *getSpecifierName(VirtSpecifier VS);
+  static const char *getSpecifierName(Specifier VS);
 
 };
 
 /// ClassVirtSpecifiers - Represents a C++0x class-virt-specifier-seq.
 class ClassVirtSpecifiers {
 public:
-  enum ClassVirtSpecifier {
+  enum Specifier {
     CVS_None = 0,
     CVS_Final = 1,
     CVS_Explicit = 2
@@ -1512,7 +1512,7 @@
 
   ClassVirtSpecifiers() : Specifiers(0) { }
 
-  bool SetSpecifier(ClassVirtSpecifier CVS, SourceLocation Loc,
+  bool SetSpecifier(Specifier CVS, SourceLocation Loc,
                     const char *&PrevSpec);
 
   bool isFinalSpecified() const { return Specifiers & CVS_Final; }
@@ -1526,7 +1526,7 @@
 
   SourceLocation CVS_finalLoc, CVS_explicitLoc;
 
-  static const char *getSpecifierName(ClassVirtSpecifier CVS);
+  static const char *getSpecifierName(Specifier CVS);
 };
 
 } // end namespace clang

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=124036&r1=124035&r2=124036&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Sat Jan 22 10:56:46 2011
@@ -807,9 +807,9 @@
 
   // There are four options here.  If we have 'struct foo;', then this
   // is either a forward declaration or a friend declaration, which
-  // have to be treated differently.  If we have 'struct foo {...' or
-  // 'struct foo :...' then this is a definition. Otherwise we have
-  // something like 'struct foo xyz', a reference.
+  // have to be treated differently.  If we have 'struct foo {...',
+  // 'struct foo :...' or 'struct foo <class-virt-specifier>' then this is a
+  // definition. Otherwise we have something like 'struct foo xyz', a reference.
   // However, in some contexts, things look like declarations but are just
   // references, e.g.
   // new struct s;
@@ -819,7 +819,9 @@
   Sema::TagUseKind TUK;
   if (SuppressDeclarations)
     TUK = Sema::TUK_Reference;
-  else if (Tok.is(tok::l_brace) || (getLang().CPlusPlus && Tok.is(tok::colon))){
+  else if (Tok.is(tok::l_brace) || 
+           (getLang().CPlusPlus && Tok.is(tok::colon)) ||
+           isCXX0XClassVirtSpecifier() != ClassVirtSpecifiers::CVS_None) {
     if (DS.isFriendSpecified()) {
       // C++ [class.friend]p2:
       //   A class shall not be defined in a friend declaration.
@@ -1004,7 +1006,8 @@
   // If there is a body, parse it and inform the actions module.
   if (TUK == Sema::TUK_Definition) {
     assert(Tok.is(tok::l_brace) ||
-           (getLang().CPlusPlus && Tok.is(tok::colon)));
+           (getLang().CPlusPlus && Tok.is(tok::colon)) ||
+           isCXX0XClassVirtSpecifier() != ClassVirtSpecifiers::CVS_None);
     if (getLang().CPlusPlus)
       ParseCXXMemberSpecification(StartLoc, TagType, TagOrTempResult.get());
     else
@@ -1268,7 +1271,10 @@
 ///         override
 ///         final
 ///         new
-VirtSpecifiers::VirtSpecifier Parser::isCXX0XVirtSpecifier() const {
+VirtSpecifiers::Specifier Parser::isCXX0XVirtSpecifier() const {
+  if (!getLang().CPlusPlus0x)
+    return VirtSpecifiers::VS_None;
+
   if (Tok.is(tok::kw_new))
     return VirtSpecifiers::VS_New;
 
@@ -1297,17 +1303,14 @@
 ///         virt-specifier
 ///         virt-specifier-seq virt-specifier
 void Parser::ParseOptionalCXX0XVirtSpecifierSeq(VirtSpecifiers &VS) {
-  if (!getLang().CPlusPlus0x)
-    return;
-
   while (true) {
-    VirtSpecifiers::VirtSpecifier Specifier = isCXX0XVirtSpecifier();
+    VirtSpecifiers::Specifier 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;
+    const char *PrevSpec = 0;
     if (VS.SetSpecifier(Specifier, Tok.getLocation(), PrevSpec))
       Diag(Tok.getLocation(), diag::err_duplicate_virt_specifier)
         << PrevSpec
@@ -1317,6 +1320,58 @@
   }
 }
 
+/// isCXX0XClassVirtSpecifier - Determine whether the next token is a C++0x
+/// class-virt-specifier.
+///
+///       class-virt-specifier:
+///         final
+///         explicit
+ClassVirtSpecifiers::Specifier Parser::isCXX0XClassVirtSpecifier() const {
+  if (!getLang().CPlusPlus0x)
+    return ClassVirtSpecifiers::CVS_None;
+
+  if (Tok.is(tok::kw_explicit))
+    return ClassVirtSpecifiers::CVS_Explicit;
+
+  if (Tok.is(tok::identifier)) {
+    IdentifierInfo *II = Tok.getIdentifierInfo();
+  
+    // Initialize the contextual keywords.
+    if (!Ident_final) {
+      Ident_final = &PP.getIdentifierTable().get("final");
+      Ident_override = &PP.getIdentifierTable().get("override");
+    }
+
+    if (II == Ident_final)
+      return ClassVirtSpecifiers::CVS_Final;
+  }
+
+  return ClassVirtSpecifiers::CVS_None;
+}
+
+/// ParseOptionalCXX0XClassVirtSpecifierSeq - Parse a class-virt-specifier-seq.
+///
+///       class-virt-specifier-seq:
+///         class-virt-specifier
+///         class-virt-specifier-seq class-virt-specifier
+void Parser::ParseOptionalCXX0XClassVirtSpecifierSeq(ClassVirtSpecifiers &CVS) {
+  while (true) {
+    ClassVirtSpecifiers::Specifier Specifier = isCXX0XClassVirtSpecifier();
+    if (Specifier == ClassVirtSpecifiers::CVS_None)
+      return;
+
+    // C++ [class]p1:
+    // A class-virt-specifier-seq shall contain at most one of each 
+    // class-virt-specifier.
+    const char *PrevSpec = 0;
+    if (CVS.SetSpecifier(Specifier, Tok.getLocation(), PrevSpec))
+      Diag(Tok.getLocation(), diag::err_duplicate_class_virt_specifier)
+       << PrevSpec
+       << FixItHint::CreateRemoval(Tok.getLocation());
+    ConsumeToken();
+  }
+}
+
 /// ParseCXXClassMemberDeclaration - Parse a C++ class member declaration.
 ///
 ///       member-declaration:
@@ -1697,6 +1752,9 @@
   if (TagDecl)
     Actions.ActOnTagStartDefinition(getCurScope(), TagDecl);
 
+  ClassVirtSpecifiers CVS;
+  ParseOptionalCXX0XClassVirtSpecifierSeq(CVS);
+
   if (Tok.is(tok::colon)) {
     ParseBaseClause(TagDecl);
 

Modified: cfe/trunk/lib/Sema/DeclSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/DeclSpec.cpp?rev=124036&r1=124035&r2=124036&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/DeclSpec.cpp (original)
+++ cfe/trunk/lib/Sema/DeclSpec.cpp Sat Jan 22 10:56:46 2011
@@ -669,7 +669,7 @@
   }
 }
 
-bool VirtSpecifiers::SetSpecifier(VirtSpecifier VS, SourceLocation Loc,
+bool VirtSpecifiers::SetSpecifier(Specifier VS, SourceLocation Loc,
                                   const char *&PrevSpec) {
   if (Specifiers & VS) {
     PrevSpec = getSpecifierName(VS);
@@ -688,7 +688,7 @@
   return false;
 }
 
-const char *VirtSpecifiers::getSpecifierName(VirtSpecifier VS) {
+const char *VirtSpecifiers::getSpecifierName(Specifier VS) {
   switch (VS) {
   default: assert(0 && "Unknown specifier");
   case VS_Override: return "override";
@@ -697,8 +697,7 @@
   }
 }
 
-bool ClassVirtSpecifiers::SetSpecifier(ClassVirtSpecifier CVS, 
-                                       SourceLocation Loc,
+bool ClassVirtSpecifiers::SetSpecifier(Specifier CVS, SourceLocation Loc,
                                        const char *&PrevSpec) {
   if (Specifiers & CVS) {
     PrevSpec = getSpecifierName(CVS);
@@ -716,7 +715,7 @@
   return false;
 }
 
-const char *ClassVirtSpecifiers::getSpecifierName(ClassVirtSpecifier CVS) {
+const char *ClassVirtSpecifiers::getSpecifierName(Specifier CVS) {
   switch (CVS) {
   default: assert(0 && "Unknown specifier");
   case CVS_Final: return "final";

Added: cfe/trunk/test/CXX/class/p1-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class/p1-0x.cpp?rev=124036&view=auto
==============================================================================
--- cfe/trunk/test/CXX/class/p1-0x.cpp (added)
+++ cfe/trunk/test/CXX/class/p1-0x.cpp Sat Jan 22 10:56:46 2011
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x
+namespace Test1 {
+
+class A final { };
+class B explicit { };
+class C final explicit { };
+class D final final { }; // expected-error {{class already marked 'final'}}
+class E explicit explicit { }; // expected-error {{class already marked 'explicit'}}
+
+}





More information about the cfe-commits mailing list