@@ -19479,11 +19479,13 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
1947919479 // representable as an int.
1948019480
1948119481 // Complain if the value is not representable in an int.
19482- if (!isRepresentableIntegerValue(Context, EnumVal, Context.IntTy))
19483- Diag(IdLoc, diag::ext_enum_value_not_int)
19484- << toString(EnumVal, 10) << Val->getSourceRange()
19485- << (EnumVal.isUnsigned() || EnumVal.isNonNegative());
19486- else if (!Context.hasSameType(Val->getType(), Context.IntTy)) {
19482+ if (!isRepresentableIntegerValue(Context, EnumVal, Context.IntTy)) {
19483+ Diag(IdLoc, getLangOpts().C23
19484+ ? diag::warn_c17_compat_enum_value_not_int
19485+ : diag::ext_c23_enum_value_not_int)
19486+ << 0 << toString(EnumVal, 10) << Val->getSourceRange()
19487+ << (EnumVal.isUnsigned() || EnumVal.isNonNegative());
19488+ } else if (!Context.hasSameType(Val->getType(), Context.IntTy)) {
1948719489 // Force the type of the expression to 'int'.
1948819490 Val = ImpCastExprToType(Val, Context.IntTy, CK_IntegralCast).get();
1948919491 }
@@ -19558,17 +19560,22 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
1955819560
1955919561 // If we're not in C++, diagnose the overflow of enumerator values,
1956019562 // which in C99 means that the enumerator value is not representable in
19561- // an int (C99 6.7.2.2p2). However, we support GCC's extension that
19562- // permits enumerator values that are representable in some larger
19563- // integral type.
19564- if (!getLangOpts().CPlusPlus && !T.isNull())
19565- Diag(IdLoc, diag::warn_enum_value_overflow);
19566- } else if (!getLangOpts().CPlusPlus &&
19567- !EltTy->isDependentType() &&
19563+ // an int (C99 6.7.2.2p2). However C23 permits enumerator values that
19564+ // are representable in some larger integral type and we allow it in
19565+ // older language modes as an extension.
19566+ // Exclude fixed enumerators since they are diagnosed with an error for
19567+ // this case.
19568+ if (!getLangOpts().CPlusPlus && !T.isNull() && !Enum->isFixed())
19569+ Diag(IdLoc, getLangOpts().C23
19570+ ? diag::warn_c17_compat_enum_value_not_int
19571+ : diag::ext_c23_enum_value_not_int)
19572+ << 1 << toString(EnumVal, 10) << 1;
19573+ } else if (!getLangOpts().CPlusPlus && !EltTy->isDependentType() &&
1956819574 !isRepresentableIntegerValue(Context, EnumVal, EltTy)) {
1956919575 // Enforce C99 6.7.2.2p2 even when we compute the next value.
19570- Diag(IdLoc, diag::ext_enum_value_not_int)
19571- << toString(EnumVal, 10) << 1;
19576+ Diag(IdLoc, getLangOpts().C23 ? diag::warn_c17_compat_enum_value_not_int
19577+ : diag::ext_c23_enum_value_not_int)
19578+ << 1 << toString(EnumVal, 10) << 1;
1957219579 }
1957319580 }
1957419581 }
@@ -19887,9 +19894,6 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
1988719894 return;
1988819895 }
1988919896
19890- // TODO: If the result value doesn't fit in an int, it must be a long or long
19891- // long value. ISO C does not support this, but GCC does as an extension,
19892- // emit a warning.
1989319897 unsigned IntWidth = Context.getTargetInfo().getIntWidth();
1989419898 unsigned CharWidth = Context.getTargetInfo().getCharWidth();
1989519899 unsigned ShortWidth = Context.getTargetInfo().getShortWidth();
@@ -19898,13 +19902,14 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
1989819902 // reverse the list.
1989919903 unsigned NumNegativeBits = 0;
1990019904 unsigned NumPositiveBits = 0;
19905+ bool MembersRepresentableByInt = true;
1990119906
1990219907 for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
1990319908 EnumConstantDecl *ECD =
1990419909 cast_or_null<EnumConstantDecl>(Elements[i]);
1990519910 if (!ECD) continue; // Already issued a diagnostic.
1990619911
19907- const llvm::APSInt & InitVal = ECD->getInitVal();
19912+ llvm::APSInt InitVal = ECD->getInitVal();
1990819913
1990919914 // Keep track of the size of positive and negative values.
1991019915 if (InitVal.isUnsigned() || InitVal.isNonNegative()) {
@@ -19916,6 +19921,8 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
1991619921 NumNegativeBits =
1991719922 std::max(NumNegativeBits, (unsigned)InitVal.getSignificantBits());
1991819923 }
19924+ MembersRepresentableByInt &=
19925+ isRepresentableIntegerValue(Context, InitVal, Context.IntTy);
1991919926 }
1992019927
1992119928 // If we have an empty set of enumerators we still need one bit.
@@ -19937,7 +19944,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
1993719944 // int, long long int, or unsigned long long int.
1993819945 // C99 6.4.4.3p2:
1993919946 // An identifier declared as an enumeration constant has type int.
19940- // The C99 rule is modified by a gcc extension
19947+ // The C99 rule is modified by C23.
1994119948 QualType BestPromotionType;
1994219949
1994319950 bool Packed = Enum->hasAttr<PackedAttr>();
@@ -20031,7 +20038,7 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
2003120038 auto *ECD = cast_or_null<EnumConstantDecl>(D);
2003220039 if (!ECD) continue; // Already issued a diagnostic.
2003320040
20034- // Standard C says the enumerators have int type, but we allow, as an
20041+ // C99 says the enumerators have int type, but we allow, as an
2003520042 // extension, the enumerators to be larger than int size. If each
2003620043 // enumerator value fits in an int, type it as an int, otherwise type it the
2003720044 // same as the enumerator decl itself. This means that in "enum { X = 1U }"
@@ -20045,9 +20052,14 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
2004520052 QualType NewTy;
2004620053 unsigned NewWidth;
2004720054 bool NewSign;
20048- if (!getLangOpts().CPlusPlus &&
20049- !Enum->isFixed() &&
20050- isRepresentableIntegerValue(Context, InitVal, Context.IntTy)) {
20055+ if (!getLangOpts().CPlusPlus && !Enum->isFixed() &&
20056+ MembersRepresentableByInt) {
20057+ // C23 6.7.3.3.3p15:
20058+ // The enumeration member type for an enumerated type without fixed
20059+ // underlying type upon completion is:
20060+ // - int if all the values of the enumeration are representable as an
20061+ // int; or,
20062+ // - the enumerated type
2005120063 NewTy = Context.IntTy;
2005220064 NewWidth = IntWidth;
2005320065 NewSign = true;
0 commit comments