Skip to content

Commit 0bf3140

Browse files
committed
Implement C++0x scoped enumerations, from Daniel Wallin! (and tweaked a
bit by me). llvm-svn: 116122
1 parent 959fcc6 commit 0bf3140

28 files changed

+512
-69
lines changed

clang/docs/LanguageExtensions.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ <h1>Clang Language Extensions</h1>
4242
<li><a href="#cxx_auto_type">C++0x type inference</a></li>
4343
<li><a href="#cxx_variadic_templates">C++0x variadic templates</a></li>
4444
<li><a href="#cxx_inline_namespaces">C++0x inline namespaces</a></li>
45+
<li><a href="#cxx_strong_enums">C++0x strongly-typed enumerations</a></li>
4546
<li><a href="#cxx_trailing_return">C++0x trailing return type</a></li>
4647
</ul>
4748
<li><a href="#blocks">Blocks</a></li>
@@ -368,6 +369,11 @@ <h3 id="cxx_trailing_return">C++0x trailing return type</h3>
368369
<p>Use <tt>__has_feature(cxx_trailing_return)</tt> to determine if support for
369370
the alternate function declaration syntax with trailing return type is enabled.</p>
370371

372+
<h3 id="cxx_strong_enums">C++0x strongly typed enumerations</h3>
373+
374+
<p>Use <tt>__has_feature(cxx_strong_enums)</tt> to determine if support for
375+
strongly typed, scoped enumerations is enabled.</p>
376+
371377
<!-- ======================================================================= -->
372378
<h2 id="blocks">Blocks</h2>
373379
<!-- ======================================================================= -->

clang/include/clang/AST/Decl.h

Lines changed: 63 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1825,6 +1825,14 @@ class TagDecl
18251825
unsigned NumPositiveBits : 8;
18261826
unsigned NumNegativeBits : 8;
18271827

1828+
/// IsScoped - True if this is tag declaration is a scoped enumeration. Only
1829+
/// possible in C++0x mode.
1830+
bool IsScoped : 1;
1831+
1832+
/// IsFixed - True if this is an enumeration with fixed underlying type. Only
1833+
/// possible in C++0x mode.
1834+
bool IsFixed : 1;
1835+
18281836
private:
18291837
SourceLocation TagKeywordLoc;
18301838
SourceLocation RBraceLoc;
@@ -2008,7 +2016,19 @@ class EnumDecl : public TagDecl {
20082016
/// IntegerType - This represent the integer type that the enum corresponds
20092017
/// to for code generation purposes. Note that the enumerator constants may
20102018
/// have a different type than this does.
2011-
QualType IntegerType;
2019+
///
2020+
/// If the underlying integer type was explicitly stated in the source
2021+
/// code, this is a TypeSourceInfo* for that type. Otherwise this type
2022+
/// was automatically deduced somehow, and this is a Type*.
2023+
///
2024+
/// Normally if IsFixed(), this would contain a TypeSourceInfo*, but in
2025+
/// some cases it won't.
2026+
///
2027+
/// The underlying type of an enumeration never has any qualifiers, so
2028+
/// we can get away with just storing a raw Type*, and thus save an
2029+
/// extra pointer when TypeSourceInfo is needed.
2030+
2031+
llvm::PointerUnion<const Type*, TypeSourceInfo*> IntegerType;
20122032

20132033
/// PromotionType - The integer type that values of this type should
20142034
/// promote to. In C, enumerators are generally of an integer type
@@ -2029,11 +2049,14 @@ class EnumDecl : public TagDecl {
20292049
};
20302050

20312051
EnumDecl(DeclContext *DC, SourceLocation L,
2032-
IdentifierInfo *Id, EnumDecl *PrevDecl, SourceLocation TKL)
2052+
IdentifierInfo *Id, EnumDecl *PrevDecl, SourceLocation TKL,
2053+
bool Scoped, bool Fixed)
20332054
: TagDecl(Enum, TTK_Enum, DC, L, Id, PrevDecl, TKL), InstantiatedFrom(0) {
2034-
IntegerType = QualType();
2055+
IntegerType = (const Type*)0;
20352056
NumNegativeBits = 0;
20362057
NumPositiveBits = 0;
2058+
IsScoped = Scoped;
2059+
IsFixed = Fixed;
20372060
}
20382061
public:
20392062
EnumDecl *getCanonicalDecl() {
@@ -2052,7 +2075,8 @@ class EnumDecl : public TagDecl {
20522075

20532076
static EnumDecl *Create(ASTContext &C, DeclContext *DC,
20542077
SourceLocation L, IdentifierInfo *Id,
2055-
SourceLocation TKL, EnumDecl *PrevDecl);
2078+
SourceLocation TKL, EnumDecl *PrevDecl,
2079+
bool IsScoped, bool IsFixed);
20562080
static EnumDecl *Create(ASTContext &C, EmptyShell Empty);
20572081

20582082
/// completeDefinition - When created, the EnumDecl corresponds to a
@@ -2092,10 +2116,25 @@ class EnumDecl : public TagDecl {
20922116

20932117
/// getIntegerType - Return the integer type this enum decl corresponds to.
20942118
/// This returns a null qualtype for an enum forward definition.
2095-
QualType getIntegerType() const { return IntegerType; }
2119+
QualType getIntegerType() const {
2120+
if (!IntegerType)
2121+
return QualType();
2122+
if (const Type* T = IntegerType.dyn_cast<const Type*>())
2123+
return QualType(T, 0);
2124+
return IntegerType.get<TypeSourceInfo*>()->getType();
2125+
}
20962126

20972127
/// \brief Set the underlying integer type.
2098-
void setIntegerType(QualType T) { IntegerType = T; }
2128+
void setIntegerType(QualType T) { IntegerType = T.getTypePtr(); }
2129+
2130+
/// \brief Set the underlying integer type source info.
2131+
void setIntegerTypeSourceInfo(TypeSourceInfo* TInfo) { IntegerType = TInfo; }
2132+
2133+
/// \brief Return the type source info for the underlying integer type,
2134+
/// if no type source info exists, return 0.
2135+
TypeSourceInfo* getIntegerTypeSourceInfo() const {
2136+
return IntegerType.dyn_cast<TypeSourceInfo*>();
2137+
}
20992138

21002139
/// \brief Returns the width in bits requred to store all the
21012140
/// non-negative enumerators of this enum.
@@ -2123,6 +2162,22 @@ class EnumDecl : public TagDecl {
21232162
NumNegativeBits = Num;
21242163
}
21252164

2165+
/// \brief Returns true if this is a C++0x scoped enumeration.
2166+
bool isScoped() const {
2167+
return IsScoped;
2168+
}
2169+
2170+
/// \brief Returns true if this is a C++0x enumeration with fixed underlying
2171+
/// type.
2172+
bool isFixed() const {
2173+
return IsFixed;
2174+
}
2175+
2176+
/// \brief Returns true if this can be considered a complete type.
2177+
bool isComplete() const {
2178+
return isDefinition() || isFixed();
2179+
}
2180+
21262181
/// \brief Returns the enumeration (declared within the template)
21272182
/// from which this enumeration type was instantiated, or NULL if
21282183
/// this enumeration was not instantiated from any template.
@@ -2135,6 +2190,8 @@ class EnumDecl : public TagDecl {
21352190
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
21362191
static bool classof(const EnumDecl *D) { return true; }
21372192
static bool classofKind(Kind K) { return K == Enum; }
2193+
2194+
friend class ASTDeclReader;
21382195
};
21392196

21402197

clang/include/clang/AST/Type.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -879,6 +879,9 @@ class Type {
879879

880880
/// \brief Determine whether this type is an integral or enumeration type.
881881
bool isIntegralOrEnumerationType() const;
882+
/// \brief Determine whether this type is an integral or unscoped enumeration
883+
/// type.
884+
bool isIntegralOrUnscopedEnumerationType() const;
882885

883886
/// Floating point categories.
884887
bool isRealFloatingType() const; // C99 6.2.5p10 (float, double, long double)

clang/include/clang/Basic/DiagnosticParseKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,9 @@ def err_friend_decl_defines_class : Error<
384384
def warn_deleted_function_accepted_as_extension: ExtWarn<
385385
"deleted function definition accepted as a C++0x extension">, InGroup<CXX0x>;
386386

387+
def err_scoped_enum_missing_identifier : Error<
388+
"scoped enumeration requires a name">;
389+
387390
// Language specific pragmas
388391
// - Generic warnings
389392
def warn_pragma_expected_lparen : Warning<

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,20 @@ def err_final_function_overridden : Error<
826826
"declaration of %0 overrides a 'final' function">;
827827
def err_final_base : Error<
828828
"derivation from 'final' %0">;
829+
830+
// C++0x scoped enumerations
831+
def err_enum_invalid_underlying : Error<
832+
"non-integral type %0 is an invalid underlying type">;
833+
def err_enumerator_too_large : Error<
834+
"enumerator value is not representable in the underlying type %0">;
835+
def err_enumerator_wrapped : Error<
836+
"enumerator value %0 is not representable in the underlying type %1">;
837+
def err_enum_redeclare_type_mismatch : Error<
838+
"enumeration redeclared with different underlying type">;
839+
def err_enum_redeclare_fixed_mismatch : Error<
840+
"enumeration previously declared with %select{non|}0fixed underlying type">;
841+
def err_enum_redeclare_scoped_mismatch : Error<
842+
"enumeration previously declared as %select{un|}0scoped">;
829843

830844
// Objective-C++
831845
def err_objc_decls_may_only_appear_in_global_scope : Error<

clang/include/clang/Sema/Sema.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -785,7 +785,8 @@ class Sema {
785785
IdentifierInfo *Name, SourceLocation NameLoc,
786786
AttributeList *Attr, AccessSpecifier AS,
787787
MultiTemplateParamsArg TemplateParameterLists,
788-
bool &OwnedDecl, bool &IsDependent);
788+
bool &OwnedDecl, bool &IsDependent, bool ScopedEnum,
789+
TypeResult UnderlyingType);
789790

790791
TypeResult ActOnDependentTag(Scope *S,
791792
unsigned TagSpec,

clang/lib/AST/ASTContext.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5154,10 +5154,10 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) {
51545154
//===----------------------------------------------------------------------===//
51555155

51565156
unsigned ASTContext::getIntWidth(QualType T) {
5157-
if (T->isBooleanType())
5158-
return 1;
51595157
if (EnumType *ET = dyn_cast<EnumType>(T))
51605158
T = ET->getDecl()->getIntegerType();
5159+
if (T->isBooleanType())
5160+
return 1;
51615161
// For builtin types, just use the standard type sizing method
51625162
return (unsigned)getTypeSize(T);
51635163
}

clang/lib/AST/ASTImporter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1622,7 +1622,7 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) {
16221622
EnumDecl *D2 = EnumDecl::Create(Importer.getToContext(), DC, Loc,
16231623
Name.getAsIdentifierInfo(),
16241624
Importer.Import(D->getTagKeywordLoc()),
1625-
0);
1625+
0, D->isScoped(), D->isFixed());
16261626
// Import the qualifier, if any.
16271627
if (D->getQualifier()) {
16281628
NestedNameSpecifier *NNS = Importer.Import(D->getQualifier());

clang/lib/AST/Decl.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1615,22 +1615,25 @@ void TagDecl::setQualifierInfo(NestedNameSpecifier *Qualifier,
16151615

16161616
EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
16171617
IdentifierInfo *Id, SourceLocation TKL,
1618-
EnumDecl *PrevDecl) {
1619-
EnumDecl *Enum = new (C) EnumDecl(DC, L, Id, PrevDecl, TKL);
1618+
EnumDecl *PrevDecl, bool IsScoped, bool IsFixed) {
1619+
EnumDecl *Enum = new (C) EnumDecl(DC, L, Id, PrevDecl, TKL,
1620+
IsScoped, IsFixed);
16201621
C.getTypeDeclType(Enum, PrevDecl);
16211622
return Enum;
16221623
}
16231624

16241625
EnumDecl *EnumDecl::Create(ASTContext &C, EmptyShell Empty) {
1625-
return new (C) EnumDecl(0, SourceLocation(), 0, 0, SourceLocation());
1626+
return new (C) EnumDecl(0, SourceLocation(), 0, 0, SourceLocation(),
1627+
false, false);
16261628
}
16271629

16281630
void EnumDecl::completeDefinition(QualType NewType,
16291631
QualType NewPromotionType,
16301632
unsigned NumPositiveBits,
16311633
unsigned NumNegativeBits) {
16321634
assert(!isDefinition() && "Cannot redefine enums!");
1633-
IntegerType = NewType;
1635+
if (!IntegerType)
1636+
IntegerType = NewType.getTypePtr();
16341637
PromotionType = NewPromotionType;
16351638
setNumPositiveBits(NumPositiveBits);
16361639
setNumNegativeBits(NumNegativeBits);

clang/lib/AST/DeclBase.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,7 @@ bool DeclContext::isDependentContext() const {
516516

517517
bool DeclContext::isTransparentContext() const {
518518
if (DeclKind == Decl::Enum)
519-
return true; // FIXME: Check for C++0x scoped enums
519+
return !cast<EnumDecl>(this)->isScoped();
520520
else if (DeclKind == Decl::LinkageSpec)
521521
return true;
522522
else if (DeclKind >= Decl::firstRecord && DeclKind <= Decl::lastRecord)

0 commit comments

Comments
 (0)