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 <ikuk...@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 <ikuk...@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 <ikuk...@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 <ikuk...@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 <ikuk...@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 <ikuk...@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 <ikuk...@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 <ikuk...@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 <ikuk...@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 <ikuk...@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 <ikuk...@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 <ikuk...@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 <ikuk...@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 <ikuk...@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 <ikuk...@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); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits