summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/Type.cpp7
-rw-r--r--clang/lib/Sema/SemaDecl.cpp44
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiateDecl.cpp3
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);
}
}
OpenPOWER on IntegriCloud