diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index 4901b6029d9ce..bcb63f719de10 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -8474,29 +8474,22 @@ 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; + clang::ASTContext &ast = lldb_ast->getASTContext(); + unsigned NumNegativeBits = 0; + unsigned NumPositiveBits = 0; + ast.computeEnumBits(enum_decl->enumerators(), NumNegativeBits, + NumPositiveBits); - 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(); + clang::QualType BestPromotionType; + clang::QualType BestType; + ast.computeBestEnumTypes(/*IsPacked=*/false, NumNegativeBits, + NumPositiveBits, BestType, BestPromotionType); enum_decl->completeDefinition(enum_decl->getIntegerType(), - promotion_qual_type, NumPositiveBits, + BestPromotionType, NumPositiveBits, NumNegativeBits); } return true; 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..2a73dc5357fe7 --- /dev/null +++ b/lldb/test/API/lang/cpp/enum_promotion/TestCPPEnumPromotion.py @@ -0,0 +1,36 @@ +""" +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): + 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..bcdb0adff5d40 --- /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 +}