diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-10-08 23:50:27 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-10-08 23:50:27 +0000 |
commit | 1274ccd90aec0b205fc838c3d504821ccfb55482 (patch) | |
tree | 209ddeed0149062574d71825566c959c214ffa39 /lib/AST/Type.cpp | |
parent | 258bcbc1474b47b5bd349a438786010fd60e9a0d (diff) |
Implement C++0x scoped enumerations, from Daniel Wallin! (and tweaked a
bit by me).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@116122 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/Type.cpp')
-rw-r--r-- | lib/AST/Type.cpp | 57 |
1 files changed, 38 insertions, 19 deletions
diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 61390c8539..11afea0446 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -409,11 +409,10 @@ bool Type::isIntegerType() const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() >= BuiltinType::Bool && BT->getKind() <= BuiltinType::Int128; - if (const TagType *TT = dyn_cast<TagType>(CanonicalType)) + if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) // Incomplete enum types are not treated as integer types. // FIXME: In C++, enum types are never integer types. - if (TT->getDecl()->isEnum() && TT->getDecl()->isDefinition()) - return true; + return ET->getDecl()->isComplete(); return false; } @@ -449,9 +448,8 @@ bool Type::isIntegralType(ASTContext &Ctx) const { BT->getKind() <= BuiltinType::Int128; if (!Ctx.getLangOptions().CPlusPlus) - if (const TagType *TT = dyn_cast<TagType>(CanonicalType)) - if (TT->getDecl()->isEnum() && TT->getDecl()->isDefinition()) - return true; // Complete enum types are integral in C. + if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) + return ET->getDecl()->isComplete(); // Complete enum types are integral in C. return false; } @@ -463,13 +461,28 @@ bool Type::isIntegralOrEnumerationType() const { // Check for a complete enum type; incomplete enum types are not properly an // enumeration type in the sense required here. - if (const TagType *TT = dyn_cast<TagType>(CanonicalType)) - if (TT->getDecl()->isEnum() && TT->getDecl()->isDefinition()) - return true; + if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) + return ET->getDecl()->isComplete(); return false; } +bool Type::isIntegralOrUnscopedEnumerationType() const { + if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) + return BT->getKind() >= BuiltinType::Bool && + BT->getKind() <= BuiltinType::Int128; + + // Check for a complete enum type; incomplete enum types are not properly an + // enumeration type in the sense required here. + // C++0x: However, if the underlying type of the enum is fixed, it is + // considered complete. + if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) + return ET->getDecl()->isComplete() && !ET->getDecl()->isScoped(); + + return false; +} + + bool Type::isBooleanType() const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() == BuiltinType::Bool; @@ -573,8 +586,8 @@ bool Type::isRealType() const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() >= BuiltinType::Bool && BT->getKind() <= BuiltinType::LongDouble; - if (const TagType *TT = dyn_cast<TagType>(CanonicalType)) - return TT->getDecl()->isEnum() && TT->getDecl()->isDefinition(); + if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) + return ET->getDecl()->isComplete() && !ET->getDecl()->isScoped(); return false; } @@ -585,20 +598,21 @@ bool Type::isArithmeticType() const { if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) // GCC allows forward declaration of enum types (forbid by C99 6.7.2.3p2). // If a body isn't seen by the time we get here, return false. - return ET->getDecl()->isDefinition(); + // + // C++0x: Enumerations are not arithmetic types. For now, just return + // false for scoped enumerations since that will disable any + // unwanted implicit conversions. + return !ET->getDecl()->isScoped() && ET->getDecl()->isComplete(); return isa<ComplexType>(CanonicalType); } bool Type::isScalarType() const { if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() != BuiltinType::Void; - if (const TagType *TT = dyn_cast<TagType>(CanonicalType)) { + if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) // Enums are scalar types, but only if they are defined. Incomplete enums // are not treated as scalar types. - if (TT->getDecl()->isEnum() && TT->getDecl()->isDefinition()) - return true; - return false; - } + return ET->getDecl()->isComplete(); return isa<PointerType>(CanonicalType) || isa<BlockPointerType>(CanonicalType) || isa<MemberPointerType>(CanonicalType) || @@ -646,8 +660,12 @@ bool Type::isIncompleteType() const { // Void is the only incomplete builtin type. Per C99 6.2.5p19, it can never // be completed. return isVoidType(); - case Record: case Enum: + // An enumeration with fixed underlying type is complete (C++0x 7.2p3). + if (cast<EnumType>(CanonicalType)->getDecl()->isFixed()) + return false; + // Fall through. + case Record: // A tagged type (struct/union/enum/class) is incomplete if the decl is a // forward declaration, but not a full definition (C99 6.2.5p22). return !cast<TagType>(CanonicalType)->getDecl()->isDefinition(); @@ -763,7 +781,8 @@ bool Type::isPromotableIntegerType() const { // Enumerated types are promotable to their compatible integer types // (C99 6.3.1.1) a.k.a. its underlying type (C++ [conv.prom]p2). if (const EnumType *ET = getAs<EnumType>()){ - if (this->isDependentType() || ET->getDecl()->getPromotionType().isNull()) + if (this->isDependentType() || ET->getDecl()->getPromotionType().isNull() + || ET->getDecl()->isScoped()) return false; const BuiltinType *BT |