[clang] [clang][Sema] Fix for enums overflowing (#24667) (PR #78742)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Jan 27 12:20:23 PST 2024
https://github.com/wheatman updated https://github.com/llvm/llvm-project/pull/78742
>From 82d227ec4f4d52231fbafd1193f8f1448e8f9c4e Mon Sep 17 00:00:00 2001
From: Brian Wheatman <bwheatman at gmail.com>
Date: Fri, 19 Jan 2024 11:13:33 -0500
Subject: [PATCH] [clang][Sema] Fix for enums overflowing (#24667)
Enums which do not have a specified type can only grow to bigger types
which contain more bits than the prior types. This means that the
largest signed integer type cannot grow to the largest unsigned integer types.
Fixes #24667
---
clang/docs/ReleaseNotes.rst | 2 ++
clang/lib/Sema/SemaDecl.cpp | 29 +++++++++++++++++++----------
clang/test/SemaCXX/enum.cpp | 2 ++
3 files changed, 23 insertions(+), 10 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index aa06e2b60ce9155..d9e060536d8747b 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -109,6 +109,8 @@ Improvements to Clang's time-trace
Bug Fixes in This Version
-------------------------
+- Fixes miscompilation when an enum has a specified value such that the auto
+ increment overflows a signed long. Fixes (`#24667 <https://github.com/llvm/llvm-project/issues/24667>`_)
Bug Fixes to Compiler Builtins
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index e725e187fc9ea08..37e66ef162a12d6 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -19759,8 +19759,8 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
// Complain if the value is not representable in an int.
if (!isRepresentableIntegerValue(Context, EnumVal, Context.IntTy))
Diag(IdLoc, diag::ext_enum_value_not_int)
- << toString(EnumVal, 10) << Val->getSourceRange()
- << (EnumVal.isUnsigned() || EnumVal.isNonNegative());
+ << toString(EnumVal, 10) << Val->getSourceRange()
+ << (EnumVal.isUnsigned() || EnumVal.isNonNegative());
else if (!Context.hasSameType(Val->getType(), Context.IntTy)) {
// Force the type of the expression to 'int'.
Val = ImpCastExprToType(Val, Context.IntTy, CK_IntegralCast).get();
@@ -19808,20 +19808,29 @@ EnumConstantDecl *Sema::CheckEnumConstant(EnumDecl *Enum,
// sufficient to contain the incremented value. If no such type
// exists, the program is ill-formed.
QualType T = getNextLargerIntegralType(Context, EltTy);
- if (T.isNull() || Enum->isFixed()) {
+ if (Enum->isFixed()) {
// There is no integral type larger enough to represent this
// value. Complain, then allow the value to wrap around.
EnumVal = LastEnumConst->getInitVal();
EnumVal = EnumVal.zext(EnumVal.getBitWidth() * 2);
++EnumVal;
- if (Enum->isFixed())
- // When the underlying type is fixed, this is ill-formed.
- Diag(IdLoc, diag::err_enumerator_wrapped)
- << toString(EnumVal, 10)
- << EltTy;
- else
+ // When the underlying type is fixed, this is ill-formed.
+ Diag(IdLoc, diag::err_enumerator_wrapped)
+ << toString(EnumVal, 10) << EltTy;
+
+ } else if (T.isNull()) {
+ if (EltTy->isSignedIntegerType() &&
+ (getLangOpts().CPlusPlus || getLangOpts().C23)) {
+ EltTy = Context.getCorrespondingUnsignedType(EltTy);
+ } else {
+ // There is no integral type larger enough to represent this
+ // value. Complain, then allow the value to wrap around.
+ EnumVal = LastEnumConst->getInitVal();
+ EnumVal = EnumVal.zext(EnumVal.getBitWidth() * 2);
+ ++EnumVal;
Diag(IdLoc, diag::ext_enumerator_increment_too_large)
- << toString(EnumVal, 10);
+ << toString(EnumVal, 10);
+ }
} else {
EltTy = T;
}
diff --git a/clang/test/SemaCXX/enum.cpp b/clang/test/SemaCXX/enum.cpp
index fc65fd16f8c302d..bee1d996f34fe89 100644
--- a/clang/test/SemaCXX/enum.cpp
+++ b/clang/test/SemaCXX/enum.cpp
@@ -125,3 +125,5 @@ struct PR28903 {
})
};
};
+
+enum GH24667 { GH24667_x = 9223372036854775807 , GH24667_y };
More information about the cfe-commits
mailing list