[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