[cfe-commits] r147824 - in /cfe/trunk: include/clang/Basic/DiagnosticParseKinds.td include/clang/Basic/DiagnosticSemaKinds.td include/clang/Sema/Sema.h lib/Parse/ParseDecl.cpp lib/Parse/ParseDeclCXX.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaTemplate.cpp test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp test/FixIt/fixit-cxx0x.cpp test/SemaCXX/enum-scoped.cpp
Richard Smith
richard-llvm at metafoo.co.uk
Mon Jan 9 17:33:14 PST 2012
Author: rsmith
Date: Mon Jan 9 19:33:14 2012
New Revision: 147824
URL: http://llvm.org/viewvc/llvm-project?rev=147824&view=rev
Log:
Update C++11 scoped enumeration support to match the final proposal:
- reject definitions of enums within friend declarations
- require 'enum', not 'enum class', for non-declaring references to scoped
enumerations
Modified:
cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/ParseDeclCXX.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp
cfe/trunk/test/FixIt/fixit-cxx0x.cpp
cfe/trunk/test/SemaCXX/enum-scoped.cpp
Modified: cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td?rev=147824&r1=147823&r2=147824&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td Mon Jan 9 19:33:14 2012
@@ -535,7 +535,7 @@
"missing ',' between base or member initializers">;
// C++ declarations
-def err_friend_decl_defines_class : Error<
+def err_friend_decl_defines_type : Error<
"cannot define a type in a friend declaration">;
def err_missing_whitespace_digraph : Error<
"found '<::' after a "
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=147824&r1=147823&r2=147824&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Jan 9 19:33:14 2012
@@ -1228,6 +1228,9 @@
"enumeration previously declared with %select{non|}0fixed underlying type">;
def err_enum_redeclare_scoped_mismatch : Error<
"enumeration previously declared as %select{un|}0scoped">;
+def err_enum_class_reference : Error<
+ "reference to %select{|scoped }0enumeration must use 'enum' "
+ "not 'enum class'">;
def err_only_enums_have_underlying_types : Error<
"only enumeration types have underlying types">;
def err_incomplete_type_no_underlying_type : Error<
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=147824&r1=147823&r2=147824&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Mon Jan 9 19:33:14 2012
@@ -1171,7 +1171,8 @@
AttributeList *Attr, AccessSpecifier AS,
SourceLocation ModulePrivateLoc,
MultiTemplateParamsArg TemplateParameterLists,
- bool &OwnedDecl, bool &IsDependent, bool ScopedEnum,
+ bool &OwnedDecl, bool &IsDependent,
+ SourceLocation ScopedEnumKWLoc,
bool ScopedEnumUsesClassTag, TypeResult UnderlyingType);
Decl *ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc,
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=147824&r1=147823&r2=147824&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Mon Jan 9 19:33:14 2012
@@ -2865,15 +2865,14 @@
return cutOffParsing();
}
- bool IsScopedEnum = false;
+ SourceLocation ScopedEnumKWLoc;
bool IsScopedUsingClassTag = false;
if (getLang().CPlusPlus0x &&
(Tok.is(tok::kw_class) || Tok.is(tok::kw_struct))) {
Diag(Tok, diag::warn_cxx98_compat_scoped_enum);
- IsScopedEnum = true;
IsScopedUsingClassTag = Tok.is(tok::kw_class);
- ConsumeToken();
+ ScopedEnumKWLoc = ConsumeToken();
}
// If attributes exist after tag, parse them.
@@ -2922,11 +2921,11 @@
NameLoc = ConsumeToken();
}
- if (!Name && IsScopedEnum) {
+ if (!Name && ScopedEnumKWLoc.isValid()) {
// C++0x 7.2p2: The optional identifier shall not be omitted in the
// declaration of a scoped enumeration.
Diag(Tok, diag::err_scoped_enum_missing_identifier);
- IsScopedEnum = false;
+ ScopedEnumKWLoc = SourceLocation();
IsScopedUsingClassTag = false;
}
@@ -2993,16 +2992,20 @@
}
}
- // There are three options here. If we have 'enum foo;', then this is a
- // forward declaration. If we have 'enum foo {...' then this is a
- // definition. Otherwise we have something like 'enum foo xyz', a reference.
+ // There are four options here. If we have 'friend enum foo;' then this is a
+ // friend declaration, and cannot have an accompanying definition. If we have
+ // 'enum foo;', then this is a forward declaration. If we have
+ // 'enum foo {...' then this is a definition. Otherwise we have something
+ // like 'enum foo xyz', a reference.
//
// This is needed to handle stuff like this right (C99 6.7.2.3p11):
// enum foo {..}; void bar() { enum foo; } <- new foo in bar.
// enum foo {..}; void bar() { enum foo x; } <- use of old foo.
//
Sema::TagUseKind TUK;
- if (Tok.is(tok::l_brace))
+ if (DS.isFriendSpecified())
+ TUK = Sema::TUK_Friend;
+ else if (Tok.is(tok::l_brace))
TUK = Sema::TUK_Definition;
else if (Tok.is(tok::semi))
TUK = Sema::TUK_Declaration;
@@ -3036,7 +3039,7 @@
StartLoc, SS, Name, NameLoc, attrs.getList(),
AS, DS.getModulePrivateSpecLoc(),
MultiTemplateParamsArg(Actions),
- Owned, IsDependent, IsScopedEnum,
+ Owned, IsDependent, ScopedEnumKWLoc,
IsScopedUsingClassTag, BaseType);
if (IsDependent) {
@@ -3075,9 +3078,13 @@
DS.SetTypeSpecError();
return;
}
-
- if (Tok.is(tok::l_brace))
+
+ if (Tok.is(tok::l_brace)) {
+ if (TUK == Sema::TUK_Friend)
+ Diag(Tok, diag::err_friend_decl_defines_type)
+ << SourceRange(DS.getFriendSpecLoc());
ParseEnumBody(StartLoc, TagDecl);
+ }
if (DS.SetTypeSpecType(DeclSpec::TST_enum, StartLoc,
NameLoc.isValid() ? NameLoc : StartLoc,
Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=147824&r1=147823&r2=147824&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Mon Jan 9 19:33:14 2012
@@ -1115,7 +1115,7 @@
if (DS.isFriendSpecified()) {
// C++ [class.friend]p2:
// A class shall not be defined in a friend declaration.
- Diag(Tok.getLocation(), diag::err_friend_decl_defines_class)
+ Diag(Tok.getLocation(), diag::err_friend_decl_defines_type)
<< SourceRange(DS.getFriendSpecLoc());
// Skip everything up to the semicolon, so that this looks like a proper
@@ -1277,8 +1277,9 @@
TagOrTempResult = Actions.ActOnTag(getCurScope(), TagType, TUK, StartLoc,
SS, Name, NameLoc, attrs.getList(), AS,
DS.getModulePrivateSpecLoc(),
- TParams, Owned, IsDependent, false,
- false, clang::TypeResult());
+ TParams, Owned, IsDependent,
+ SourceLocation(), false,
+ clang::TypeResult());
// If ActOnTag said the type was dependent, try again with the
// less common call.
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=147824&r1=147823&r2=147824&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Mon Jan 9 19:33:14 2012
@@ -7580,7 +7580,8 @@
SourceLocation ModulePrivateLoc,
MultiTemplateParamsArg TemplateParameterLists,
bool &OwnedDecl, bool &IsDependent,
- bool ScopedEnum, bool ScopedEnumUsesClassTag,
+ SourceLocation ScopedEnumKWLoc,
+ bool ScopedEnumUsesClassTag,
TypeResult UnderlyingType) {
// If this is not a definition, it must have a name.
assert((Name != 0 || TUK == TUK_Definition) &&
@@ -7589,6 +7590,7 @@
OwnedDecl = false;
TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec);
+ bool ScopedEnum = ScopedEnumKWLoc.isValid();
// FIXME: Check explicit specializations more carefully.
bool isExplicitSpecialization = false;
@@ -7919,6 +7921,16 @@
if (Kind == TTK_Enum && PrevTagDecl->getTagKind() == TTK_Enum) {
const EnumDecl *PrevEnum = cast<EnumDecl>(PrevTagDecl);
+ // If this is an elaborated-type-specifier for a scoped enumeration,
+ // the 'class' keyword is not necessary and not permitted.
+ if (TUK == TUK_Reference || TUK == TUK_Friend) {
+ if (ScopedEnum)
+ Diag(ScopedEnumKWLoc, diag::err_enum_class_reference)
+ << PrevEnum->isScoped()
+ << FixItHint::CreateRemoval(ScopedEnumKWLoc);
+ return PrevTagDecl;
+ }
+
// All conflicts with previous declarations are recovered by
// returning the previous declaration.
if (ScopedEnum != PrevEnum->isScoped()) {
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=147824&r1=147823&r2=147824&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Jan 9 19:33:14 2012
@@ -9851,7 +9851,7 @@
Attr, AS_public,
/*ModulePrivateLoc=*/SourceLocation(),
MultiTemplateParamsArg(), Owned, IsDependent,
- /*ScopedEnum=*/false,
+ /*ScopedEnumKWLoc=*/SourceLocation(),
/*ScopedEnumUsesClassTag=*/false,
/*UnderlyingType=*/TypeResult());
}
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=147824&r1=147823&r2=147824&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon Jan 9 19:33:14 2012
@@ -6070,7 +6070,7 @@
KWLoc, SS, Name, NameLoc, Attr, AS_none,
/*ModulePrivateLoc=*/SourceLocation(),
MultiTemplateParamsArg(*this, 0, 0),
- Owned, IsDependent, false, false,
+ Owned, IsDependent, SourceLocation(), false,
TypeResult());
assert(!IsDependent && "explicit instantiation of dependent name not yet handled");
Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp?rev=147824&r1=147823&r2=147824&view=diff
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp (original)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp Mon Jan 9 19:33:14 2012
@@ -1,6 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
-class A {}; // expected-note 3 {{previous use is here}}
+class A {}; // expected-note 4 {{previous use is here}}
+enum E {};
void a1(struct A);
void a2(class A);
@@ -12,8 +13,8 @@
friend class A;
friend union A; // expected-error {{use of 'A' with tag type that does not match previous declaration}}
- friend enum A; // expected-error {{ISO C++ forbids forward references to 'enum' types}} \
- // expected-warning {{cannot be a friend}}
+ friend enum A; // expected-error {{use of 'A' with tag type that does not match previous declaration}}
+ friend enum E; // expected-warning {{cannot be a friend}}
};
template <class T> struct B { // expected-note {{previous use is here}}
Modified: cfe/trunk/test/FixIt/fixit-cxx0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/fixit-cxx0x.cpp?rev=147824&r1=147823&r2=147824&view=diff
==============================================================================
--- cfe/trunk/test/FixIt/fixit-cxx0x.cpp (original)
+++ cfe/trunk/test/FixIt/fixit-cxx0x.cpp Mon Jan 9 19:33:14 2012
@@ -37,3 +37,12 @@
f3 override, // expected-error {{expected ';' at end of declaration}}
};
}
+
+namespace ScopedEnum {
+ enum class E { a };
+
+ enum class E b = E::a; // expected-error {{must use 'enum' not 'enum class'}}
+ struct S {
+ friend enum class E; // expected-error {{must use 'enum' not 'enum class'}}
+ };
+}
Modified: cfe/trunk/test/SemaCXX/enum-scoped.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/enum-scoped.cpp?rev=147824&r1=147823&r2=147824&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/enum-scoped.cpp (original)
+++ cfe/trunk/test/SemaCXX/enum-scoped.cpp Mon Jan 9 19:33:14 2012
@@ -147,3 +147,30 @@
const int val = 104;
enum class test1 { owner_dead = val, };
}
+
+namespace N2764 {
+ enum class E { a, b };
+ enum E x1 = E::a; // ok
+ enum class E x2 = E::a; // expected-error {{reference to scoped enumeration must use 'enum' not 'enum class'}}
+
+ enum F { a, b };
+ enum F y1 = a; // ok
+ enum class F y2 = a; // expected-error {{reference to enumeration must use 'enum' not 'enum class'}}
+
+ struct S {
+ friend enum class E; // expected-error {{reference to scoped enumeration must use 'enum' not 'enum class'}}
+ friend enum class F; // expected-error {{reference to enumeration must use 'enum' not 'enum class'}}
+
+ friend enum G {}; // expected-error {{forward reference}} expected-error {{cannot define a type in a friend declaration}}
+ friend enum class H {}; // expected-error {{cannot define a type in a friend declaration}}
+
+ enum A : int;
+ A a;
+ } s;
+
+ enum S::A : int {};
+
+ enum class B;
+}
+
+enum class N2764::B {};
More information about the cfe-commits
mailing list