Expr *val);
bool CheckEnumUnderlyingType(TypeSourceInfo *TI);
bool CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped,
- QualType EnumUnderlyingTy, const EnumDecl *Prev);
+ QualType EnumUnderlyingTy,
+ bool EnumUnderlyingIsImplicit,
+ const EnumDecl *Prev);
/// Determine whether the body of an anonymous enumeration should be skipped.
/// \param II The name of the first enumerator.
/// 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,
- const EnumDecl *Prev) {
+bool Sema::CheckEnumRedeclaration(
+ SourceLocation EnumLoc, bool IsScoped, QualType EnumUnderlyingTy,
+ bool EnumUnderlyingIsImplicit, const EnumDecl *Prev) {
bool IsFixed = !EnumUnderlyingTy.isNull();
if (IsScoped != Prev->isScoped()) {
<< 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();
// this early, because it's needed to detect if this is an incompatible
// redeclaration.
llvm::PointerUnion<const Type*, TypeSourceInfo*> EnumUnderlying;
+ bool EnumUnderlyingIsImplicit = false;
if (Kind == TTK_Enum) {
if (UnderlyingType.isInvalid() || (!UnderlyingType.get() && ScopedEnum))
if (getLangOpts().MSVCCompat || TUK == TUK_Definition) {
// Microsoft enums are always of int type.
EnumUnderlying = Context.IntTy.getTypePtr();
+ EnumUnderlyingIsImplicit = true;
}
}
}
// returning the previous declaration, unless this is a definition,
// in which case we want the caller to bail out.
if (CheckEnumRedeclaration(NameLoc.isValid() ? NameLoc : KWLoc,
- ScopedEnum, EnumUnderlyingTy, PrevEnum))
+ ScopedEnum, EnumUnderlyingTy,
+ EnumUnderlyingIsImplicit, PrevEnum))
return TUK == TUK_Declaration ? PrevTagDecl : nullptr;
}