[Lldb-commits] [clang] [lldb] [lldb] Analyze enum promotion type during parsing (PR #115005)
Ilia Kuklin via lldb-commits
lldb-commits at lists.llvm.org
Thu Feb 13 07:22:43 PST 2025
https://github.com/kuilpd updated https://github.com/llvm/llvm-project/pull/115005
>From dd65babbf4c73a0b2fc2e4aa47a9a346bd5a9adf Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Mon, 4 Nov 2024 14:33:45 +0500
Subject: [PATCH 01/15] [lldb] Analyze enum promotion type during parsing
---
clang/include/clang/AST/Decl.h | 2 +-
.../SymbolFile/DWARF/DWARFASTParserClang.cpp | 93 +++++++++++++++++++
.../TypeSystem/Clang/TypeSystemClang.cpp | 25 +----
3 files changed, 97 insertions(+), 23 deletions(-)
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index f305cbbce4c60..177f7df5bfee8 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -3910,6 +3910,7 @@ class EnumDecl : public TagDecl {
void setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED,
TemplateSpecializationKind TSK);
+public:
/// Sets the width in bits required to store all the
/// non-negative enumerators of this enum.
void setNumPositiveBits(unsigned Num) {
@@ -3921,7 +3922,6 @@ class EnumDecl : public TagDecl {
/// negative enumerators of this enum. (see getNumNegativeBits)
void setNumNegativeBits(unsigned Num) { EnumDeclBits.NumNegativeBits = Num; }
-public:
/// True if this tag declaration is a scoped enumeration. Only
/// possible in C++11 mode.
void setScoped(bool Scoped = true) { EnumDeclBits.IsScoped = Scoped; }
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index ec0004c70c6da..f8678909ce732 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -2315,6 +2315,8 @@ size_t DWARFASTParserClang::ParseChildEnumerators(
return 0;
size_t enumerators_added = 0;
+ unsigned NumNegativeBits = 0;
+ unsigned NumPositiveBits = 0;
for (DWARFDIE die : parent_die.children()) {
const dw_tag_t tag = die.Tag();
@@ -2367,8 +2369,99 @@ size_t DWARFASTParserClang::ParseChildEnumerators(
m_ast.AddEnumerationValueToEnumerationType(
clang_type, decl, name, *enum_value, enumerator_byte_size * 8);
++enumerators_added;
+
+ llvm::APSInt InitVal = ECD->getInitVal();
+ // Keep track of the size of positive and negative values.
+ if (InitVal.isUnsigned() || InitVal.isNonNegative()) {
+ // If the enumerator is zero that should still be counted as a positive
+ // bit since we need a bit to store the value zero.
+ unsigned ActiveBits = InitVal.getActiveBits();
+ NumPositiveBits = std::max({NumPositiveBits, ActiveBits, 1u});
+ } else {
+ NumNegativeBits =
+ std::max(NumNegativeBits, (unsigned)InitVal.getSignificantBits());
+ }
}
}
+
+ /// The following code follows the same logic as in Sema::ActOnEnumBody
+ /// clang/lib/Sema/SemaDecl.cpp
+ // If we have an empty set of enumerators we still need one bit.
+ // From [dcl.enum]p8
+ // If the enumerator-list is empty, the values of the enumeration are as if
+ // the enumeration had a single enumerator with value 0
+ if (!NumPositiveBits && !NumNegativeBits)
+ NumPositiveBits = 1;
+
+ clang::QualType qual_type(ClangUtil::GetQualType(clang_type));
+ clang::EnumDecl *enum_decl = qual_type->getAs<clang::EnumType>()->getDecl();
+ enum_decl->setNumPositiveBits(NumPositiveBits);
+ enum_decl->setNumNegativeBits(NumNegativeBits);
+
+ // C++0x N3000 [conv.prom]p3:
+ // An rvalue of an unscoped enumeration type whose underlying
+ // type is not fixed can be converted to an rvalue of the first
+ // of the following types that can represent all the values of
+ // the enumeration: int, unsigned int, long int, unsigned long
+ // int, long long int, or unsigned long long int.
+ // C99 6.4.4.3p2:
+ // An identifier declared as an enumeration constant has type int.
+ // The C99 rule is modified by C23.
+ clang::QualType BestPromotionType;
+ unsigned BestWidth;
+
+ auto &Context = m_ast.getASTContext();
+ unsigned LongWidth = Context.getTargetInfo().getLongWidth();
+ unsigned IntWidth = Context.getTargetInfo().getIntWidth();
+ unsigned CharWidth = Context.getTargetInfo().getCharWidth();
+ unsigned ShortWidth = Context.getTargetInfo().getShortWidth();
+
+ bool is_cpp = Language::LanguageIsCPlusPlus(
+ SymbolFileDWARF::GetLanguage(*parent_die.GetCU()));
+
+ if (NumNegativeBits) {
+ // If there is a negative value, figure out the smallest integer type (of
+ // int/long/longlong) that fits.
+ if (NumNegativeBits <= CharWidth && NumPositiveBits < CharWidth) {
+ BestWidth = CharWidth;
+ } else if (NumNegativeBits <= ShortWidth && NumPositiveBits < ShortWidth) {
+ BestWidth = ShortWidth;
+ } else if (NumNegativeBits <= IntWidth && NumPositiveBits < IntWidth) {
+ BestWidth = IntWidth;
+ } else if (NumNegativeBits <= LongWidth && NumPositiveBits < LongWidth) {
+ BestWidth = LongWidth;
+ } else {
+ BestWidth = Context.getTargetInfo().getLongLongWidth();
+ }
+ BestPromotionType = (BestWidth <= IntWidth ? Context.IntTy : qual_type);
+ } else {
+ // If there is no negative value, figure out the smallest type that fits
+ // all of the enumerator values.
+ if (NumPositiveBits <= CharWidth) {
+ BestPromotionType = Context.IntTy;
+ BestWidth = CharWidth;
+ } else if (NumPositiveBits <= ShortWidth) {
+ BestPromotionType = Context.IntTy;
+ BestWidth = ShortWidth;
+ } else if (NumPositiveBits <= IntWidth) {
+ BestWidth = IntWidth;
+ BestPromotionType = (NumPositiveBits == BestWidth || !is_cpp)
+ ? Context.UnsignedIntTy
+ : Context.IntTy;
+ } else if (NumPositiveBits <= LongWidth) {
+ BestWidth = LongWidth;
+ BestPromotionType = (NumPositiveBits == BestWidth || !is_cpp)
+ ? Context.UnsignedLongTy
+ : Context.LongTy;
+ } else {
+ BestWidth = Context.getTargetInfo().getLongLongWidth();
+ BestPromotionType = (NumPositiveBits == BestWidth || !is_cpp)
+ ? Context.UnsignedLongLongTy
+ : Context.LongLongTy;
+ }
+ }
+ enum_decl->setPromotionType(BestPromotionType);
+
return enumerators_added;
}
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 4901b6029d9ce..b7102406586d0 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -8474,30 +8474,11 @@ bool TypeSystemClang::CompleteTagDeclarationDefinition(
if (enum_decl->isCompleteDefinition())
return true;
- clang::ASTContext &ast = lldb_ast->getASTContext();
-
- /// TODO This really needs to be fixed.
-
QualType integer_type(enum_decl->getIntegerType());
if (!integer_type.isNull()) {
- unsigned NumPositiveBits = 1;
- unsigned NumNegativeBits = 0;
-
- clang::QualType promotion_qual_type;
- // If the enum integer type is less than an integer in bit width,
- // then we must promote it to an integer size.
- if (ast.getTypeSize(enum_decl->getIntegerType()) <
- ast.getTypeSize(ast.IntTy)) {
- if (enum_decl->getIntegerType()->isSignedIntegerType())
- promotion_qual_type = ast.IntTy;
- else
- promotion_qual_type = ast.UnsignedIntTy;
- } else
- promotion_qual_type = enum_decl->getIntegerType();
-
- enum_decl->completeDefinition(enum_decl->getIntegerType(),
- promotion_qual_type, NumPositiveBits,
- NumNegativeBits);
+ enum_decl->completeDefinition(
+ enum_decl->getIntegerType(), enum_decl->getPromotionType(),
+ enum_decl->getNumPositiveBits(), enum_decl->getNumNegativeBits());
}
return true;
}
>From b438c38d2c92c72117e389fe4644d9a3632c9b2c Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Tue, 5 Nov 2024 19:18:41 +0500
Subject: [PATCH 02/15] Fix enum's underlying type retrieval
---
.../Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index f8678909ce732..ecb3670617fcc 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -2393,8 +2393,8 @@ size_t DWARFASTParserClang::ParseChildEnumerators(
if (!NumPositiveBits && !NumNegativeBits)
NumPositiveBits = 1;
- clang::QualType qual_type(ClangUtil::GetQualType(clang_type));
- clang::EnumDecl *enum_decl = qual_type->getAs<clang::EnumType>()->getDecl();
+ clang::EnumDecl *enum_decl =
+ ClangUtil::GetQualType(clang_type)->getAs<clang::EnumType>()->getDecl();
enum_decl->setNumPositiveBits(NumPositiveBits);
enum_decl->setNumNegativeBits(NumNegativeBits);
@@ -2433,7 +2433,8 @@ size_t DWARFASTParserClang::ParseChildEnumerators(
} else {
BestWidth = Context.getTargetInfo().getLongLongWidth();
}
- BestPromotionType = (BestWidth <= IntWidth ? Context.IntTy : qual_type);
+ BestPromotionType =
+ BestWidth <= IntWidth ? Context.IntTy : enum_decl->getIntegerType();
} else {
// If there is no negative value, figure out the smallest type that fits
// all of the enumerator values.
>From 4d60eec90e51abc66a4298dd2f948d76ff79d87f Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Tue, 5 Nov 2024 19:19:14 +0500
Subject: [PATCH 03/15] Add a test
---
.../test/API/lang/cpp/enum_promotion/Makefile | 3 ++
.../enum_promotion/TestCPPEnumPromotion.py | 37 +++++++++++++++++++
.../test/API/lang/cpp/enum_promotion/main.cpp | 22 +++++++++++
3 files changed, 62 insertions(+)
create mode 100644 lldb/test/API/lang/cpp/enum_promotion/Makefile
create mode 100644 lldb/test/API/lang/cpp/enum_promotion/TestCPPEnumPromotion.py
create mode 100644 lldb/test/API/lang/cpp/enum_promotion/main.cpp
diff --git a/lldb/test/API/lang/cpp/enum_promotion/Makefile b/lldb/test/API/lang/cpp/enum_promotion/Makefile
new file mode 100644
index 0000000000000..99998b20bcb05
--- /dev/null
+++ b/lldb/test/API/lang/cpp/enum_promotion/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git a/lldb/test/API/lang/cpp/enum_promotion/TestCPPEnumPromotion.py b/lldb/test/API/lang/cpp/enum_promotion/TestCPPEnumPromotion.py
new file mode 100644
index 0000000000000..a4eed53c8d80f
--- /dev/null
+++ b/lldb/test/API/lang/cpp/enum_promotion/TestCPPEnumPromotion.py
@@ -0,0 +1,37 @@
+"""
+Test LLDB type promotion of unscoped enums.
+"""
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class TestCPPEnumPromotion(TestBase):
+
+ @skipIf(debug_info=no_match(["dwarf", "dwo"]))
+ def test(self):
+ self.build()
+ lldbutil.run_to_source_breakpoint(
+ self, "// break here", lldb.SBFileSpec("main.cpp")
+ )
+ UChar_promoted = self.frame().FindVariable("UChar_promoted")
+ UShort_promoted = self.frame().FindVariable("UShort_promoted")
+ UInt_promoted = self.frame().FindVariable("UInt_promoted")
+ SLong_promoted = self.frame().FindVariable("SLong_promoted")
+ ULong_promoted = self.frame().FindVariable("ULong_promoted")
+ NChar_promoted = self.frame().FindVariable("NChar_promoted")
+ NShort_promoted = self.frame().FindVariable("NShort_promoted")
+ NInt_promoted = self.frame().FindVariable("NInt_promoted")
+ NLong_promoted = self.frame().FindVariable("NLong_promoted")
+
+ # Check that LLDB's promoted type is the same as the compiler's
+ self.expect_expr("+EnumUChar::UChar", result_type=UChar_promoted.type.name)
+ self.expect_expr("+EnumUShort::UShort", result_type=UShort_promoted.type.name)
+ self.expect_expr("+EnumUInt::UInt", result_type=UInt_promoted.type.name)
+ self.expect_expr("+EnumSLong::SLong", result_type=SLong_promoted.type.name)
+ self.expect_expr("+EnumULong::ULong", result_type=ULong_promoted.type.name)
+ self.expect_expr("+EnumNChar::NChar", result_type=NChar_promoted.type.name)
+ self.expect_expr("+EnumNShort::NShort", result_type=NShort_promoted.type.name)
+ self.expect_expr("+EnumNInt::NInt", result_type=NInt_promoted.type.name)
+ self.expect_expr("+EnumNLong::NLong", result_type=NLong_promoted.type.name)
diff --git a/lldb/test/API/lang/cpp/enum_promotion/main.cpp b/lldb/test/API/lang/cpp/enum_promotion/main.cpp
new file mode 100644
index 0000000000000..fafb96f6c7b07
--- /dev/null
+++ b/lldb/test/API/lang/cpp/enum_promotion/main.cpp
@@ -0,0 +1,22 @@
+enum EnumUChar { UChar = 1 };
+enum EnumUShort { UShort = 0x101 };
+enum EnumUInt { UInt = 0x10001 };
+enum EnumSLong { SLong = 0x100000001 };
+enum EnumULong { ULong = 0xFFFFFFFFFFFFFFF0 };
+enum EnumNChar { NChar = -1 };
+enum EnumNShort { NShort= -0x101 };
+enum EnumNInt { NInt = -0x10001 };
+enum EnumNLong { NLong = -0x100000001 };
+
+int main() {
+ auto UChar_promoted = +EnumUChar::UChar;
+ auto UShort_promoted = +EnumUShort::UShort;
+ auto UInt_promoted = +EnumUInt::UInt;
+ auto SLong_promoted = +EnumSLong::SLong;
+ auto ULong_promoted = +EnumULong::ULong;
+ auto NChar_promoted = +EnumNChar::NChar;
+ auto NShort_promoted = +EnumNShort::NShort;
+ auto NInt_promoted = +EnumNInt::NInt;
+ auto NLong_promoted = +EnumNLong::NLong;
+ return 0; // break here
+}
>From 66d60748399742c3383074b471e70b111ade065c Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Tue, 5 Nov 2024 20:10:58 +0500
Subject: [PATCH 04/15] Fix formatting
---
lldb/test/API/lang/cpp/enum_promotion/TestCPPEnumPromotion.py | 2 +-
lldb/test/API/lang/cpp/enum_promotion/main.cpp | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/lldb/test/API/lang/cpp/enum_promotion/TestCPPEnumPromotion.py b/lldb/test/API/lang/cpp/enum_promotion/TestCPPEnumPromotion.py
index a4eed53c8d80f..3cf110441a0ae 100644
--- a/lldb/test/API/lang/cpp/enum_promotion/TestCPPEnumPromotion.py
+++ b/lldb/test/API/lang/cpp/enum_promotion/TestCPPEnumPromotion.py
@@ -7,8 +7,8 @@
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
-class TestCPPEnumPromotion(TestBase):
+class TestCPPEnumPromotion(TestBase):
@skipIf(debug_info=no_match(["dwarf", "dwo"]))
def test(self):
self.build()
diff --git a/lldb/test/API/lang/cpp/enum_promotion/main.cpp b/lldb/test/API/lang/cpp/enum_promotion/main.cpp
index fafb96f6c7b07..bcdb0adff5d40 100644
--- a/lldb/test/API/lang/cpp/enum_promotion/main.cpp
+++ b/lldb/test/API/lang/cpp/enum_promotion/main.cpp
@@ -4,7 +4,7 @@ enum EnumUInt { UInt = 0x10001 };
enum EnumSLong { SLong = 0x100000001 };
enum EnumULong { ULong = 0xFFFFFFFFFFFFFFF0 };
enum EnumNChar { NChar = -1 };
-enum EnumNShort { NShort= -0x101 };
+enum EnumNShort { NShort = -0x101 };
enum EnumNInt { NInt = -0x10001 };
enum EnumNLong { NLong = -0x100000001 };
>From 16ca7cfad7c8229abd2896387f387e04b9e9241b Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Fri, 20 Dec 2024 23:52:16 +0500
Subject: [PATCH 05/15] Move enum type and width computations to a separate
function
---
clang/include/clang/Sema/Sema.h | 7 ++
clang/lib/Sema/SemaDecl.cpp | 81 +++++++++++++++++++
.../SymbolFile/DWARF/DWARFASTParserClang.cpp | 65 ++-------------
3 files changed, 96 insertions(+), 57 deletions(-)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 1870d1271c556..4d1bc965a89e0 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -4003,6 +4003,13 @@ class Sema final : public SemaBase {
SourceLocation IdLoc, IdentifierInfo *Id,
const ParsedAttributesView &Attrs,
SourceLocation EqualLoc, Expr *Val);
+
+ bool ComputeBestEnumProperties(ASTContext &Context, EnumDecl *Enum,
+ bool isCpp, bool isPacked,
+ unsigned NumNegativeBits,
+ unsigned NumPositiveBits, unsigned &BestWidth,
+ QualType &BestType,
+ QualType &BestPromotionType);
void ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
Decl *EnumDecl, ArrayRef<Decl *> Elements, Scope *S,
const ParsedAttributesView &Attr);
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 6eedc77ed20a0..60a3366e96473 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -20128,6 +20128,87 @@ bool Sema::IsValueInFlagEnum(const EnumDecl *ED, const llvm::APInt &Val,
return !(FlagMask & Val) || (AllowMask && !(FlagMask & ~Val));
}
+bool Sema::ComputeBestEnumProperties(ASTContext &Context, EnumDecl *Enum,
+ bool is_cpp, bool isPacked,
+ unsigned NumNegativeBits,
+ unsigned NumPositiveBits,
+ unsigned &BestWidth, QualType &BestType,
+ QualType &BestPromotionType) {
+ unsigned IntWidth = Context.getTargetInfo().getIntWidth();
+ unsigned CharWidth = Context.getTargetInfo().getCharWidth();
+ unsigned ShortWidth = Context.getTargetInfo().getShortWidth();
+ bool enum_too_large = false;
+ if (NumNegativeBits) {
+ // If there is a negative value, figure out the smallest integer type (of
+ // int/long/longlong) that fits.
+ // If it's packed, check also if it fits a char or a short.
+ if (isPacked && NumNegativeBits <= CharWidth &&
+ NumPositiveBits < CharWidth) {
+ BestType = Context.SignedCharTy;
+ BestWidth = CharWidth;
+ } else if (isPacked && NumNegativeBits <= ShortWidth &&
+ NumPositiveBits < ShortWidth) {
+ BestType = Context.ShortTy;
+ BestWidth = ShortWidth;
+ } else if (NumNegativeBits <= IntWidth && NumPositiveBits < IntWidth) {
+ BestType = Context.IntTy;
+ BestWidth = IntWidth;
+ } else {
+ BestWidth = Context.getTargetInfo().getLongWidth();
+
+ if (NumNegativeBits <= BestWidth && NumPositiveBits < BestWidth) {
+ BestType = Context.LongTy;
+ } else {
+ BestWidth = Context.getTargetInfo().getLongLongWidth();
+
+ if (NumNegativeBits > BestWidth || NumPositiveBits >= BestWidth)
+ enum_too_large = true;
+ BestType = Context.LongLongTy;
+ }
+ }
+ BestPromotionType = (BestWidth <= IntWidth ? Context.IntTy : BestType);
+ } else {
+ // If there is no negative value, figure out the smallest type that fits
+ // all of the enumerator values.
+ // If it's packed, check also if it fits a char or a short.
+ if (isPacked && NumPositiveBits <= CharWidth) {
+ BestType = Context.UnsignedCharTy;
+ BestPromotionType = Context.IntTy;
+ BestWidth = CharWidth;
+ } else if (isPacked && NumPositiveBits <= ShortWidth) {
+ BestType = Context.UnsignedShortTy;
+ BestPromotionType = Context.IntTy;
+ BestWidth = ShortWidth;
+ } else if (NumPositiveBits <= IntWidth) {
+ BestType = Context.UnsignedIntTy;
+ BestWidth = IntWidth;
+ BestPromotionType = (NumPositiveBits == BestWidth || !is_cpp)
+ ? Context.UnsignedIntTy
+ : Context.IntTy;
+ } else if (NumPositiveBits <=
+ (BestWidth = Context.getTargetInfo().getLongWidth())) {
+ BestType = Context.UnsignedLongTy;
+ BestPromotionType = (NumPositiveBits == BestWidth || !is_cpp)
+ ? Context.UnsignedLongTy
+ : Context.LongTy;
+ } else {
+ BestWidth = Context.getTargetInfo().getLongLongWidth();
+ if (NumPositiveBits > BestWidth) {
+ // This can happen with bit-precise integer types, but those are not
+ // allowed as the type for an enumerator per C23 6.7.2.2p4 and p12.
+ // FIXME: GCC uses __int128_t and __uint128_t for cases that fit within
+ // a 128-bit integer, we should consider doing the same.
+ enum_too_large = true;
+ }
+ BestType = Context.UnsignedLongLongTy;
+ BestPromotionType = (NumPositiveBits == BestWidth || !is_cpp)
+ ? Context.UnsignedLongLongTy
+ : Context.LongLongTy;
+ }
+ }
+ return enum_too_large;
+}
+
void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
Decl *EnumDeclX, ArrayRef<Decl *> Elements, Scope *S,
const ParsedAttributesView &Attrs) {
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index ecb3670617fcc..6701f39103b54 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -2398,69 +2398,20 @@ size_t DWARFASTParserClang::ParseChildEnumerators(
enum_decl->setNumPositiveBits(NumPositiveBits);
enum_decl->setNumNegativeBits(NumNegativeBits);
- // C++0x N3000 [conv.prom]p3:
- // An rvalue of an unscoped enumeration type whose underlying
- // type is not fixed can be converted to an rvalue of the first
- // of the following types that can represent all the values of
- // the enumeration: int, unsigned int, long int, unsigned long
- // int, long long int, or unsigned long long int.
- // C99 6.4.4.3p2:
- // An identifier declared as an enumeration constant has type int.
- // The C99 rule is modified by C23.
+ auto ts_ptr = clang_type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>();
+ if (!ts_ptr)
+ return enumerators_added;
+
clang::QualType BestPromotionType;
+ clang::QualType BestType;
unsigned BestWidth;
auto &Context = m_ast.getASTContext();
- unsigned LongWidth = Context.getTargetInfo().getLongWidth();
- unsigned IntWidth = Context.getTargetInfo().getIntWidth();
- unsigned CharWidth = Context.getTargetInfo().getCharWidth();
- unsigned ShortWidth = Context.getTargetInfo().getShortWidth();
-
bool is_cpp = Language::LanguageIsCPlusPlus(
SymbolFileDWARF::GetLanguage(*parent_die.GetCU()));
-
- if (NumNegativeBits) {
- // If there is a negative value, figure out the smallest integer type (of
- // int/long/longlong) that fits.
- if (NumNegativeBits <= CharWidth && NumPositiveBits < CharWidth) {
- BestWidth = CharWidth;
- } else if (NumNegativeBits <= ShortWidth && NumPositiveBits < ShortWidth) {
- BestWidth = ShortWidth;
- } else if (NumNegativeBits <= IntWidth && NumPositiveBits < IntWidth) {
- BestWidth = IntWidth;
- } else if (NumNegativeBits <= LongWidth && NumPositiveBits < LongWidth) {
- BestWidth = LongWidth;
- } else {
- BestWidth = Context.getTargetInfo().getLongLongWidth();
- }
- BestPromotionType =
- BestWidth <= IntWidth ? Context.IntTy : enum_decl->getIntegerType();
- } else {
- // If there is no negative value, figure out the smallest type that fits
- // all of the enumerator values.
- if (NumPositiveBits <= CharWidth) {
- BestPromotionType = Context.IntTy;
- BestWidth = CharWidth;
- } else if (NumPositiveBits <= ShortWidth) {
- BestPromotionType = Context.IntTy;
- BestWidth = ShortWidth;
- } else if (NumPositiveBits <= IntWidth) {
- BestWidth = IntWidth;
- BestPromotionType = (NumPositiveBits == BestWidth || !is_cpp)
- ? Context.UnsignedIntTy
- : Context.IntTy;
- } else if (NumPositiveBits <= LongWidth) {
- BestWidth = LongWidth;
- BestPromotionType = (NumPositiveBits == BestWidth || !is_cpp)
- ? Context.UnsignedLongTy
- : Context.LongTy;
- } else {
- BestWidth = Context.getTargetInfo().getLongLongWidth();
- BestPromotionType = (NumPositiveBits == BestWidth || !is_cpp)
- ? Context.UnsignedLongLongTy
- : Context.LongLongTy;
- }
- }
+ ts_ptr->getSema()->ComputeBestEnumProperties(
+ Context, enum_decl, is_cpp, false, NumNegativeBits, NumPositiveBits,
+ BestWidth, BestType, BestPromotionType);
enum_decl->setPromotionType(BestPromotionType);
return enumerators_added;
>From 8fe2a9a6b6422eba3944ff3a941c7c57f83bd673 Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Mon, 27 Jan 2025 20:29:52 +0500
Subject: [PATCH 06/15] Use computeBestEnumTypes() from ASTContext & cleanup
code
---
clang/include/clang/Sema/Sema.h | 7 --
clang/lib/Sema/SemaDecl.cpp | 81 -------------------
.../SymbolFile/DWARF/DWARFASTParserClang.cpp | 20 +----
3 files changed, 2 insertions(+), 106 deletions(-)
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 4d1bc965a89e0..1870d1271c556 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -4003,13 +4003,6 @@ class Sema final : public SemaBase {
SourceLocation IdLoc, IdentifierInfo *Id,
const ParsedAttributesView &Attrs,
SourceLocation EqualLoc, Expr *Val);
-
- bool ComputeBestEnumProperties(ASTContext &Context, EnumDecl *Enum,
- bool isCpp, bool isPacked,
- unsigned NumNegativeBits,
- unsigned NumPositiveBits, unsigned &BestWidth,
- QualType &BestType,
- QualType &BestPromotionType);
void ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
Decl *EnumDecl, ArrayRef<Decl *> Elements, Scope *S,
const ParsedAttributesView &Attr);
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 60a3366e96473..6eedc77ed20a0 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -20128,87 +20128,6 @@ bool Sema::IsValueInFlagEnum(const EnumDecl *ED, const llvm::APInt &Val,
return !(FlagMask & Val) || (AllowMask && !(FlagMask & ~Val));
}
-bool Sema::ComputeBestEnumProperties(ASTContext &Context, EnumDecl *Enum,
- bool is_cpp, bool isPacked,
- unsigned NumNegativeBits,
- unsigned NumPositiveBits,
- unsigned &BestWidth, QualType &BestType,
- QualType &BestPromotionType) {
- unsigned IntWidth = Context.getTargetInfo().getIntWidth();
- unsigned CharWidth = Context.getTargetInfo().getCharWidth();
- unsigned ShortWidth = Context.getTargetInfo().getShortWidth();
- bool enum_too_large = false;
- if (NumNegativeBits) {
- // If there is a negative value, figure out the smallest integer type (of
- // int/long/longlong) that fits.
- // If it's packed, check also if it fits a char or a short.
- if (isPacked && NumNegativeBits <= CharWidth &&
- NumPositiveBits < CharWidth) {
- BestType = Context.SignedCharTy;
- BestWidth = CharWidth;
- } else if (isPacked && NumNegativeBits <= ShortWidth &&
- NumPositiveBits < ShortWidth) {
- BestType = Context.ShortTy;
- BestWidth = ShortWidth;
- } else if (NumNegativeBits <= IntWidth && NumPositiveBits < IntWidth) {
- BestType = Context.IntTy;
- BestWidth = IntWidth;
- } else {
- BestWidth = Context.getTargetInfo().getLongWidth();
-
- if (NumNegativeBits <= BestWidth && NumPositiveBits < BestWidth) {
- BestType = Context.LongTy;
- } else {
- BestWidth = Context.getTargetInfo().getLongLongWidth();
-
- if (NumNegativeBits > BestWidth || NumPositiveBits >= BestWidth)
- enum_too_large = true;
- BestType = Context.LongLongTy;
- }
- }
- BestPromotionType = (BestWidth <= IntWidth ? Context.IntTy : BestType);
- } else {
- // If there is no negative value, figure out the smallest type that fits
- // all of the enumerator values.
- // If it's packed, check also if it fits a char or a short.
- if (isPacked && NumPositiveBits <= CharWidth) {
- BestType = Context.UnsignedCharTy;
- BestPromotionType = Context.IntTy;
- BestWidth = CharWidth;
- } else if (isPacked && NumPositiveBits <= ShortWidth) {
- BestType = Context.UnsignedShortTy;
- BestPromotionType = Context.IntTy;
- BestWidth = ShortWidth;
- } else if (NumPositiveBits <= IntWidth) {
- BestType = Context.UnsignedIntTy;
- BestWidth = IntWidth;
- BestPromotionType = (NumPositiveBits == BestWidth || !is_cpp)
- ? Context.UnsignedIntTy
- : Context.IntTy;
- } else if (NumPositiveBits <=
- (BestWidth = Context.getTargetInfo().getLongWidth())) {
- BestType = Context.UnsignedLongTy;
- BestPromotionType = (NumPositiveBits == BestWidth || !is_cpp)
- ? Context.UnsignedLongTy
- : Context.LongTy;
- } else {
- BestWidth = Context.getTargetInfo().getLongLongWidth();
- if (NumPositiveBits > BestWidth) {
- // This can happen with bit-precise integer types, but those are not
- // allowed as the type for an enumerator per C23 6.7.2.2p4 and p12.
- // FIXME: GCC uses __int128_t and __uint128_t for cases that fit within
- // a 128-bit integer, we should consider doing the same.
- enum_too_large = true;
- }
- BestType = Context.UnsignedLongLongTy;
- BestPromotionType = (NumPositiveBits == BestWidth || !is_cpp)
- ? Context.UnsignedLongLongTy
- : Context.LongLongTy;
- }
- }
- return enum_too_large;
-}
-
void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange,
Decl *EnumDeclX, ArrayRef<Decl *> Elements, Scope *S,
const ParsedAttributesView &Attrs) {
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 6701f39103b54..f6d02e759c9c5 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -2384,12 +2384,6 @@ size_t DWARFASTParserClang::ParseChildEnumerators(
}
}
- /// The following code follows the same logic as in Sema::ActOnEnumBody
- /// clang/lib/Sema/SemaDecl.cpp
- // If we have an empty set of enumerators we still need one bit.
- // From [dcl.enum]p8
- // If the enumerator-list is empty, the values of the enumeration are as if
- // the enumeration had a single enumerator with value 0
if (!NumPositiveBits && !NumNegativeBits)
NumPositiveBits = 1;
@@ -2398,20 +2392,10 @@ size_t DWARFASTParserClang::ParseChildEnumerators(
enum_decl->setNumPositiveBits(NumPositiveBits);
enum_decl->setNumNegativeBits(NumNegativeBits);
- auto ts_ptr = clang_type.GetTypeSystem().dyn_cast_or_null<TypeSystemClang>();
- if (!ts_ptr)
- return enumerators_added;
-
clang::QualType BestPromotionType;
clang::QualType BestType;
- unsigned BestWidth;
-
- auto &Context = m_ast.getASTContext();
- bool is_cpp = Language::LanguageIsCPlusPlus(
- SymbolFileDWARF::GetLanguage(*parent_die.GetCU()));
- ts_ptr->getSema()->ComputeBestEnumProperties(
- Context, enum_decl, is_cpp, false, NumNegativeBits, NumPositiveBits,
- BestWidth, BestType, BestPromotionType);
+ m_ast.getASTContext().computeBestEnumTypes(
+ false, NumNegativeBits, NumPositiveBits, BestType, BestPromotionType);
enum_decl->setPromotionType(BestPromotionType);
return enumerators_added;
>From 515ac84fd28e893b52ec65ca27d362ac3ed52d58 Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Mon, 27 Jan 2025 23:16:49 +0500
Subject: [PATCH 07/15] Add comments
---
.../source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index f6d02e759c9c5..0137c097d2c69 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -2384,6 +2384,10 @@ size_t DWARFASTParserClang::ParseChildEnumerators(
}
}
+ // If we have an empty set of enumerators we still need one bit.
+ // From [dcl.enum]p8
+ // If the enumerator-list is empty, the values of the enumeration are as if
+ // the enumeration had a single enumerator with value 0
if (!NumPositiveBits && !NumNegativeBits)
NumPositiveBits = 1;
@@ -2395,7 +2399,7 @@ size_t DWARFASTParserClang::ParseChildEnumerators(
clang::QualType BestPromotionType;
clang::QualType BestType;
m_ast.getASTContext().computeBestEnumTypes(
- false, NumNegativeBits, NumPositiveBits, BestType, BestPromotionType);
+ /*IsPacked=*/false, NumNegativeBits, NumPositiveBits, BestType, BestPromotionType);
enum_decl->setPromotionType(BestPromotionType);
return enumerators_added;
>From 64fd77fde5c2ebbaa3187b6cf030aa0753f74ad0 Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Mon, 27 Jan 2025 23:49:02 +0500
Subject: [PATCH 08/15] Apply clang-format
---
lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 0137c097d2c69..d4100ff4dfae6 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -2399,7 +2399,8 @@ size_t DWARFASTParserClang::ParseChildEnumerators(
clang::QualType BestPromotionType;
clang::QualType BestType;
m_ast.getASTContext().computeBestEnumTypes(
- /*IsPacked=*/false, NumNegativeBits, NumPositiveBits, BestType, BestPromotionType);
+ /*IsPacked=*/false, NumNegativeBits, NumPositiveBits, BestType,
+ BestPromotionType);
enum_decl->setPromotionType(BestPromotionType);
return enumerators_added;
>From a65d8c577c6a817eac9e2187c333585f7009e858 Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Thu, 30 Jan 2025 19:48:47 +0500
Subject: [PATCH 09/15] Move updating number of enum bits to a separate
function
---
clang/include/clang/AST/ASTContext.h | 5 +++++
clang/lib/AST/ASTContext.cpp | 14 ++++++++++++++
.../SymbolFile/DWARF/DWARFASTParserClang.cpp | 11 ++---------
3 files changed, 21 insertions(+), 9 deletions(-)
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index a96b9c0a17045..b3c979c101d2e 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1726,6 +1726,11 @@ class ASTContext : public RefCountedBase<ASTContext> {
QualType getEnumType(const EnumDecl *Decl) const;
+ /// Update the maximum amount of negative and positive bits
+ /// based on the provided enumerator value.
+ void updateNumOfEnumBits(llvm::APSInt *InitVal, unsigned &NumNegativeBits,
+ unsigned &NumPositiveBits);
+
/// Compute BestType and BestPromotionType for an enum based on the highest
/// number of negative and positive bits of its elements.
/// Returns true if enum width is too large.
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index b1b9d56ccca9f..ad4f62b8701d4 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -5241,6 +5241,20 @@ QualType ASTContext::getEnumType(const EnumDecl *Decl) const {
return QualType(newType, 0);
}
+void ASTContext::updateNumOfEnumBits(llvm::APSInt *InitVal,
+ unsigned &NumNegativeBits,
+ unsigned &NumPositiveBits) {
+ if (InitVal->isUnsigned() || InitVal->isNonNegative()) {
+ // If the enumerator is zero that should still be counted as a positive
+ // bit since we need a bit to store the value zero.
+ unsigned ActiveBits = InitVal->getActiveBits();
+ NumPositiveBits = std::max({NumPositiveBits, ActiveBits, 1u});
+ } else {
+ NumNegativeBits =
+ std::max(NumNegativeBits, (unsigned)InitVal->getSignificantBits());
+ }
+}
+
bool ASTContext::computeBestEnumTypes(bool IsPacked, unsigned NumNegativeBits,
unsigned NumPositiveBits,
QualType &BestType,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index d4100ff4dfae6..20d7100e5b26c 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -2372,15 +2372,8 @@ size_t DWARFASTParserClang::ParseChildEnumerators(
llvm::APSInt InitVal = ECD->getInitVal();
// Keep track of the size of positive and negative values.
- if (InitVal.isUnsigned() || InitVal.isNonNegative()) {
- // If the enumerator is zero that should still be counted as a positive
- // bit since we need a bit to store the value zero.
- unsigned ActiveBits = InitVal.getActiveBits();
- NumPositiveBits = std::max({NumPositiveBits, ActiveBits, 1u});
- } else {
- NumNegativeBits =
- std::max(NumNegativeBits, (unsigned)InitVal.getSignificantBits());
- }
+ m_ast.getASTContext().updateNumOfEnumBits(&InitVal, NumNegativeBits,
+ NumPositiveBits);
}
}
>From 982cf255beddea35961a4fa651a38bc7a1cf485a Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Thu, 30 Jan 2025 20:00:23 +0500
Subject: [PATCH 10/15] Add dSYM to the test
---
lldb/test/API/lang/cpp/enum_promotion/TestCPPEnumPromotion.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lldb/test/API/lang/cpp/enum_promotion/TestCPPEnumPromotion.py b/lldb/test/API/lang/cpp/enum_promotion/TestCPPEnumPromotion.py
index 3cf110441a0ae..fdf33627e40a1 100644
--- a/lldb/test/API/lang/cpp/enum_promotion/TestCPPEnumPromotion.py
+++ b/lldb/test/API/lang/cpp/enum_promotion/TestCPPEnumPromotion.py
@@ -9,7 +9,7 @@
class TestCPPEnumPromotion(TestBase):
- @skipIf(debug_info=no_match(["dwarf", "dwo"]))
+ @skipIf(debug_info=no_match(["dwarf", "dwo", "dsym"]))
def test(self):
self.build()
lldbutil.run_to_source_breakpoint(
>From c5bc9865e5afa09c124a1782aa28115a6a8ea4c6 Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Sat, 1 Feb 2025 00:40:43 +0500
Subject: [PATCH 11/15] Move computing NumNegativeBits and NumPositiveBits to a
separate function
---
clang/include/clang/AST/ASTContext.h | 30 ++++++++++++++++---
clang/lib/AST/ASTContext.cpp | 14 ---------
.../SymbolFile/DWARF/DWARFASTParserClang.cpp | 15 ++--------
3 files changed, 29 insertions(+), 30 deletions(-)
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index b3c979c101d2e..9cb33d51fa678 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1726,11 +1726,33 @@ class ASTContext : public RefCountedBase<ASTContext> {
QualType getEnumType(const EnumDecl *Decl) const;
- /// Update the maximum amount of negative and positive bits
- /// based on the provided enumerator value.
- void updateNumOfEnumBits(llvm::APSInt *InitVal, unsigned &NumNegativeBits,
- unsigned &NumPositiveBits);
+ /// Compute the maximum number of negative and positive bits
+ /// of enum elements.
+ template <typename RangeT>
+ void computeEnumBits(RangeT EnumConstants, unsigned &NumNegativeBits,
+ unsigned &NumPositiveBits) {
+ for (auto ECD : EnumConstants) {
+ llvm::APSInt InitVal = ECD->getInitVal();
+ if (InitVal.isUnsigned() || InitVal.isNonNegative()) {
+ // If the enumerator is zero that should still be counted as a positive
+ // bit since we need a bit to store the value zero.
+ unsigned ActiveBits = InitVal.getActiveBits();
+ NumPositiveBits = std::max({NumPositiveBits, ActiveBits, 1u});
+ } else {
+ NumNegativeBits =
+ std::max(NumNegativeBits, (unsigned)InitVal.getSignificantBits());
+ }
+ }
+
+ // If we have an empty set of enumerators we still need one bit.
+ // From [dcl.enum]p8
+ // If the enumerator-list is empty, the values of the enumeration are as if
+ // the enumeration had a single enumerator with value 0
+ if (!NumPositiveBits && !NumNegativeBits)
+ NumPositiveBits = 1;
+ return;
+ }
/// Compute BestType and BestPromotionType for an enum based on the highest
/// number of negative and positive bits of its elements.
/// Returns true if enum width is too large.
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index ad4f62b8701d4..b1b9d56ccca9f 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -5241,20 +5241,6 @@ QualType ASTContext::getEnumType(const EnumDecl *Decl) const {
return QualType(newType, 0);
}
-void ASTContext::updateNumOfEnumBits(llvm::APSInt *InitVal,
- unsigned &NumNegativeBits,
- unsigned &NumPositiveBits) {
- if (InitVal->isUnsigned() || InitVal->isNonNegative()) {
- // If the enumerator is zero that should still be counted as a positive
- // bit since we need a bit to store the value zero.
- unsigned ActiveBits = InitVal->getActiveBits();
- NumPositiveBits = std::max({NumPositiveBits, ActiveBits, 1u});
- } else {
- NumNegativeBits =
- std::max(NumNegativeBits, (unsigned)InitVal->getSignificantBits());
- }
-}
-
bool ASTContext::computeBestEnumTypes(bool IsPacked, unsigned NumNegativeBits,
unsigned NumPositiveBits,
QualType &BestType,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 20d7100e5b26c..73b5162c35494 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -44,6 +44,7 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Type.h"
#include "clang/Basic/Specifiers.h"
+#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
#include "llvm/DebugInfo/DWARF/DWARFTypePrinter.h"
@@ -2369,23 +2370,13 @@ size_t DWARFASTParserClang::ParseChildEnumerators(
m_ast.AddEnumerationValueToEnumerationType(
clang_type, decl, name, *enum_value, enumerator_byte_size * 8);
++enumerators_added;
-
- llvm::APSInt InitVal = ECD->getInitVal();
- // Keep track of the size of positive and negative values.
- m_ast.getASTContext().updateNumOfEnumBits(&InitVal, NumNegativeBits,
- NumPositiveBits);
}
}
- // If we have an empty set of enumerators we still need one bit.
- // From [dcl.enum]p8
- // If the enumerator-list is empty, the values of the enumeration are as if
- // the enumeration had a single enumerator with value 0
- if (!NumPositiveBits && !NumNegativeBits)
- NumPositiveBits = 1;
-
clang::EnumDecl *enum_decl =
ClangUtil::GetQualType(clang_type)->getAs<clang::EnumType>()->getDecl();
+ m_ast.getASTContext().computeEnumBits(enum_decl->enumerators(),
+ NumNegativeBits, NumPositiveBits);
enum_decl->setNumPositiveBits(NumPositiveBits);
enum_decl->setNumNegativeBits(NumNegativeBits);
>From 47532c92f5cee38bdfaffe864b161d737bb86365 Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Sat, 1 Feb 2025 00:41:42 +0500
Subject: [PATCH 12/15] Remove test skipping
---
lldb/test/API/lang/cpp/enum_promotion/TestCPPEnumPromotion.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/lldb/test/API/lang/cpp/enum_promotion/TestCPPEnumPromotion.py b/lldb/test/API/lang/cpp/enum_promotion/TestCPPEnumPromotion.py
index fdf33627e40a1..2a73dc5357fe7 100644
--- a/lldb/test/API/lang/cpp/enum_promotion/TestCPPEnumPromotion.py
+++ b/lldb/test/API/lang/cpp/enum_promotion/TestCPPEnumPromotion.py
@@ -9,7 +9,6 @@
class TestCPPEnumPromotion(TestBase):
- @skipIf(debug_info=no_match(["dwarf", "dwo", "dsym"]))
def test(self):
self.build()
lldbutil.run_to_source_breakpoint(
>From 2bfd311a6661c9f2cd21f8cbb742be9219739937 Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Wed, 12 Feb 2025 21:36:29 +0500
Subject: [PATCH 13/15] Remove previous computeEnumBits implementation
---
clang/include/clang/AST/ASTContext.h | 27 -------------------
.../SymbolFile/DWARF/DWARFASTParserClang.cpp | 1 -
2 files changed, 28 deletions(-)
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 9cb33d51fa678..a96b9c0a17045 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -1726,33 +1726,6 @@ class ASTContext : public RefCountedBase<ASTContext> {
QualType getEnumType(const EnumDecl *Decl) const;
- /// Compute the maximum number of negative and positive bits
- /// of enum elements.
- template <typename RangeT>
- void computeEnumBits(RangeT EnumConstants, unsigned &NumNegativeBits,
- unsigned &NumPositiveBits) {
- for (auto ECD : EnumConstants) {
- llvm::APSInt InitVal = ECD->getInitVal();
- if (InitVal.isUnsigned() || InitVal.isNonNegative()) {
- // If the enumerator is zero that should still be counted as a positive
- // bit since we need a bit to store the value zero.
- unsigned ActiveBits = InitVal.getActiveBits();
- NumPositiveBits = std::max({NumPositiveBits, ActiveBits, 1u});
- } else {
- NumNegativeBits =
- std::max(NumNegativeBits, (unsigned)InitVal.getSignificantBits());
- }
- }
-
- // If we have an empty set of enumerators we still need one bit.
- // From [dcl.enum]p8
- // If the enumerator-list is empty, the values of the enumeration are as if
- // the enumeration had a single enumerator with value 0
- if (!NumPositiveBits && !NumNegativeBits)
- NumPositiveBits = 1;
-
- return;
- }
/// Compute BestType and BestPromotionType for an enum based on the highest
/// number of negative and positive bits of its elements.
/// Returns true if enum width is too large.
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index 73b5162c35494..cfb50d162067a 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -44,7 +44,6 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/Type.h"
#include "clang/Basic/Specifiers.h"
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
#include "llvm/DebugInfo/DWARF/DWARFTypePrinter.h"
>From fe6a395a90d6545d0a7864d2e3723e39f1bd8099 Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Wed, 12 Feb 2025 22:12:31 +0500
Subject: [PATCH 14/15] Move computing enum parameters to TypeSystemClang
---
clang/include/clang/AST/Decl.h | 2 +-
.../SymbolFile/DWARF/DWARFASTParserClang.cpp | 17 -----------------
.../TypeSystem/Clang/TypeSystemClang.cpp | 18 +++++++++++++++---
3 files changed, 16 insertions(+), 21 deletions(-)
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 177f7df5bfee8..f305cbbce4c60 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -3910,7 +3910,6 @@ class EnumDecl : public TagDecl {
void setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED,
TemplateSpecializationKind TSK);
-public:
/// Sets the width in bits required to store all the
/// non-negative enumerators of this enum.
void setNumPositiveBits(unsigned Num) {
@@ -3922,6 +3921,7 @@ class EnumDecl : public TagDecl {
/// negative enumerators of this enum. (see getNumNegativeBits)
void setNumNegativeBits(unsigned Num) { EnumDeclBits.NumNegativeBits = Num; }
+public:
/// True if this tag declaration is a scoped enumeration. Only
/// possible in C++11 mode.
void setScoped(bool Scoped = true) { EnumDeclBits.IsScoped = Scoped; }
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index cfb50d162067a..ec0004c70c6da 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -2315,8 +2315,6 @@ size_t DWARFASTParserClang::ParseChildEnumerators(
return 0;
size_t enumerators_added = 0;
- unsigned NumNegativeBits = 0;
- unsigned NumPositiveBits = 0;
for (DWARFDIE die : parent_die.children()) {
const dw_tag_t tag = die.Tag();
@@ -2371,21 +2369,6 @@ size_t DWARFASTParserClang::ParseChildEnumerators(
++enumerators_added;
}
}
-
- clang::EnumDecl *enum_decl =
- ClangUtil::GetQualType(clang_type)->getAs<clang::EnumType>()->getDecl();
- m_ast.getASTContext().computeEnumBits(enum_decl->enumerators(),
- NumNegativeBits, NumPositiveBits);
- enum_decl->setNumPositiveBits(NumPositiveBits);
- enum_decl->setNumNegativeBits(NumNegativeBits);
-
- clang::QualType BestPromotionType;
- clang::QualType BestType;
- m_ast.getASTContext().computeBestEnumTypes(
- /*IsPacked=*/false, NumNegativeBits, NumPositiveBits, BestType,
- BestPromotionType);
- enum_decl->setPromotionType(BestPromotionType);
-
return enumerators_added;
}
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index b7102406586d0..e7b2aeababdf0 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -8474,11 +8474,23 @@ bool TypeSystemClang::CompleteTagDeclarationDefinition(
if (enum_decl->isCompleteDefinition())
return true;
+ clang::ASTContext &ast = lldb_ast->getASTContext();
+
+ unsigned NumNegativeBits = 0;
+ unsigned NumPositiveBits = 0;
+ ast.computeEnumBits(enum_decl->enumerators(), NumNegativeBits,
+ NumPositiveBits);
+
+ clang::QualType BestPromotionType;
+ clang::QualType BestType;
+ ast.computeBestEnumTypes(/*IsPacked=*/false, NumNegativeBits, NumPositiveBits,
+ BestType, BestPromotionType);
+
QualType integer_type(enum_decl->getIntegerType());
if (!integer_type.isNull()) {
- enum_decl->completeDefinition(
- enum_decl->getIntegerType(), enum_decl->getPromotionType(),
- enum_decl->getNumPositiveBits(), enum_decl->getNumNegativeBits());
+ enum_decl->completeDefinition(enum_decl->getIntegerType(),
+ BestPromotionType, NumPositiveBits,
+ NumNegativeBits);
}
return true;
}
>From 88abe76c02a79e846859ebdc185c37acdfd6b41e Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Thu, 13 Feb 2025 20:03:25 +0500
Subject: [PATCH 15/15] Move the computing code into the 'if' block
---
.../TypeSystem/Clang/TypeSystemClang.cpp | 22 +++++++++----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index e7b2aeababdf0..bcb63f719de10 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -8474,20 +8474,20 @@ bool TypeSystemClang::CompleteTagDeclarationDefinition(
if (enum_decl->isCompleteDefinition())
return true;
- clang::ASTContext &ast = lldb_ast->getASTContext();
+ QualType integer_type(enum_decl->getIntegerType());
+ if (!integer_type.isNull()) {
+ clang::ASTContext &ast = lldb_ast->getASTContext();
- unsigned NumNegativeBits = 0;
- unsigned NumPositiveBits = 0;
- ast.computeEnumBits(enum_decl->enumerators(), NumNegativeBits,
- NumPositiveBits);
+ unsigned NumNegativeBits = 0;
+ unsigned NumPositiveBits = 0;
+ ast.computeEnumBits(enum_decl->enumerators(), NumNegativeBits,
+ NumPositiveBits);
- clang::QualType BestPromotionType;
- clang::QualType BestType;
- ast.computeBestEnumTypes(/*IsPacked=*/false, NumNegativeBits, NumPositiveBits,
- BestType, BestPromotionType);
+ clang::QualType BestPromotionType;
+ clang::QualType BestType;
+ ast.computeBestEnumTypes(/*IsPacked=*/false, NumNegativeBits,
+ NumPositiveBits, BestType, BestPromotionType);
- QualType integer_type(enum_decl->getIntegerType());
- if (!integer_type.isNull()) {
enum_decl->completeDefinition(enum_decl->getIntegerType(),
BestPromotionType, NumPositiveBits,
NumNegativeBits);
More information about the lldb-commits
mailing list