diff options
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/AST/Type.cpp | 7 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 44 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 3 |
3 files changed, 22 insertions, 32 deletions
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index d306f7dd613..2690a3faf72 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -1997,12 +1997,7 @@ bool Type::isIncompleteType(NamedDecl **Def) const { EnumDecl *EnumD = cast<EnumType>(CanonicalType)->getDecl(); if (Def) *Def = EnumD; - - // An enumeration with fixed underlying type is complete (C++0x 7.2p3). - if (EnumD->isFixed()) - return false; - - return !EnumD->isCompleteDefinition(); + return !EnumD->isComplete(); } case Record: { // A tagged type (struct/union/enum/class) is incomplete if the decl is a diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index b70e2306ca2..7d7b274b815 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -13236,11 +13236,9 @@ bool Sema::CheckEnumUnderlyingType(TypeSourceInfo *TI) { /// Check whether this is a valid redeclaration of a previous enumeration. /// \return true if the redeclaration was invalid. -bool Sema::CheckEnumRedeclaration( - SourceLocation EnumLoc, bool IsScoped, QualType EnumUnderlyingTy, - bool EnumUnderlyingIsImplicit, const EnumDecl *Prev) { - bool IsFixed = !EnumUnderlyingTy.isNull(); - +bool Sema::CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped, + QualType EnumUnderlyingTy, bool IsFixed, + const EnumDecl *Prev) { if (IsScoped != Prev->isScoped()) { Diag(EnumLoc, diag::err_enum_redeclare_scoped_mismatch) << Prev->isScoped(); @@ -13260,10 +13258,6 @@ bool Sema::CheckEnumRedeclaration( << Prev->getIntegerTypeRange(); return true; } - } else if (IsFixed && !Prev->isFixed() && EnumUnderlyingIsImplicit) { - ; - } else if (!IsFixed && Prev->isFixed() && !Prev->getIntegerTypeSourceInfo()) { - ; } else if (IsFixed != Prev->isFixed()) { Diag(EnumLoc, diag::err_enum_redeclare_fixed_mismatch) << Prev->isFixed(); @@ -13559,14 +13553,14 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // this early, because it's needed to detect if this is an incompatible // redeclaration. llvm::PointerUnion<const Type*, TypeSourceInfo*> EnumUnderlying; - bool EnumUnderlyingIsImplicit = false; + bool IsFixed = !UnderlyingType.isUnset() || ScopedEnum; if (Kind == TTK_Enum) { - if (UnderlyingType.isInvalid() || (!UnderlyingType.get() && ScopedEnum)) + if (UnderlyingType.isInvalid() || (!UnderlyingType.get() && ScopedEnum)) { // No underlying type explicitly specified, or we failed to parse the // type, default to int. EnumUnderlying = Context.IntTy.getTypePtr(); - else if (UnderlyingType.get()) { + } else if (UnderlyingType.get()) { // C++0x 7.2p2: The type-specifier-seq of an enum-base shall name an // integral type; any cv-qualification is ignored. TypeSourceInfo *TI = nullptr; @@ -13582,11 +13576,12 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, EnumUnderlying = Context.IntTy.getTypePtr(); } else if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { - if (getLangOpts().MSVCCompat || TUK == TUK_Definition) { - // Microsoft enums are always of int type. + // For MSVC ABI compatibility, unfixed enums must use an underlying type + // of 'int'. However, if this is an unfixed forward declaration, don't set + // the underlying type unless the user enables -fms-compatibility. This + // makes unfixed forward declared enums incomplete and is more conforming. + if (TUK == TUK_Definition || getLangOpts().MSVCCompat) EnumUnderlying = Context.IntTy.getTypePtr(); - EnumUnderlyingIsImplicit = true; - } } } @@ -13612,8 +13607,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, if (Kind == TTK_Enum) { New = EnumDecl::Create(Context, SearchDC, KWLoc, Loc, Name, nullptr, - ScopedEnum, ScopedEnumUsesClassTag, - !EnumUnderlying.isNull()); + ScopedEnum, ScopedEnumUsesClassTag, IsFixed); // If this is an undefined enum, bail. if (TUK != TUK_Definition && !Invalid) return nullptr; @@ -13992,7 +13986,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // in which case we want the caller to bail out. if (CheckEnumRedeclaration(NameLoc.isValid() ? NameLoc : KWLoc, ScopedEnum, EnumUnderlyingTy, - EnumUnderlyingIsImplicit, PrevEnum)) + IsFixed, PrevEnum)) return TUK == TUK_Declaration ? PrevTagDecl : nullptr; } @@ -14208,7 +14202,7 @@ CreateNewDecl: // enum X { A, B, C } D; D should chain to X. New = EnumDecl::Create(Context, SearchDC, KWLoc, Loc, Name, cast_or_null<EnumDecl>(PrevDecl), ScopedEnum, - ScopedEnumUsesClassTag, !EnumUnderlying.isNull()); + ScopedEnumUsesClassTag, IsFixed); if (isStdAlignValT && (!StdAlignValT || getStdAlignValT()->isImplicit())) StdAlignValT = cast<EnumDecl>(New); @@ -14216,8 +14210,7 @@ CreateNewDecl: // If this is an undefined enum, warn. if (TUK != TUK_Definition && !Invalid) { TagDecl *Def; - if (!EnumUnderlyingIsImplicit && - (getLangOpts().CPlusPlus11 || getLangOpts().ObjC2) && + if (IsFixed && (getLangOpts().CPlusPlus11 || getLangOpts().ObjC2) && cast<EnumDecl>(New)->isFixed()) { // C++0x: 7.2p2: opaque-enum-declaration. // Conflicts are diagnosed above. Do nothing. @@ -14249,6 +14242,7 @@ CreateNewDecl: else ED->setIntegerType(QualType(EnumUnderlying.get<const Type*>(), 0)); ED->setPromotionType(ED->getIntegerType()); + assert(ED->isComplete() && "enum with type should be complete"); } } else { // struct/union/class @@ -15707,7 +15701,7 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum, &EnumVal).get())) { // C99 6.7.2.2p2: Make sure we have an integer constant expression. } else { - if (Enum->isFixed()) { + if (Enum->isComplete()) { EltTy = Enum->getIntegerType(); // In Obj-C and Microsoft mode, require the enumeration value to be @@ -16218,7 +16212,9 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange, if (LangOpts.ShortEnums) Packed = true; - if (Enum->isFixed()) { + // If the enum already has a type because it is fixed or dictated by the + // target, promote that type instead of analyzing the enumerators. + if (Enum->isComplete()) { BestType = Enum->getIntegerType(); if (BestType->isPromotableIntegerType()) BestPromotionType = Context.getPromotedIntegerType(BestType); diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 15b53ca7612..1ccd0c84c42 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1041,8 +1041,7 @@ Decl *TemplateDeclInstantiator::VisitEnumDecl(EnumDecl *D) { SemaRef.SubstType(TI->getType(), TemplateArgs, UnderlyingLoc, DeclarationName()); SemaRef.CheckEnumRedeclaration(Def->getLocation(), Def->isScoped(), - DefnUnderlying, - /*EnumUnderlyingIsImplicit=*/false, Enum); + DefnUnderlying, /*IsFixed=*/true, Enum); } } |

