Skip to content

Commit bc4fb61

Browse files
kuilpdjoaosaffran
authored andcommitted
[lldb] Analyze enum promotion type during parsing (llvm#115005)
The information about an enum's best promotion type is discarded after compilation and is not present in debug info. This patch repeats the same analysis of each enum value as in the front-end to determine the best promotion type during DWARF info parsing. Fixes llvm#86989
1 parent 58e0339 commit bc4fb61

File tree

4 files changed

+71
-17
lines changed

4 files changed

+71
-17
lines changed

lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8474,29 +8474,22 @@ bool TypeSystemClang::CompleteTagDeclarationDefinition(
84748474
if (enum_decl->isCompleteDefinition())
84758475
return true;
84768476

8477-
clang::ASTContext &ast = lldb_ast->getASTContext();
8478-
8479-
/// TODO This really needs to be fixed.
8480-
84818477
QualType integer_type(enum_decl->getIntegerType());
84828478
if (!integer_type.isNull()) {
8483-
unsigned NumPositiveBits = 1;
8479+
clang::ASTContext &ast = lldb_ast->getASTContext();
8480+
84848481
unsigned NumNegativeBits = 0;
8482+
unsigned NumPositiveBits = 0;
8483+
ast.computeEnumBits(enum_decl->enumerators(), NumNegativeBits,
8484+
NumPositiveBits);
84858485

8486-
clang::QualType promotion_qual_type;
8487-
// If the enum integer type is less than an integer in bit width,
8488-
// then we must promote it to an integer size.
8489-
if (ast.getTypeSize(enum_decl->getIntegerType()) <
8490-
ast.getTypeSize(ast.IntTy)) {
8491-
if (enum_decl->getIntegerType()->isSignedIntegerType())
8492-
promotion_qual_type = ast.IntTy;
8493-
else
8494-
promotion_qual_type = ast.UnsignedIntTy;
8495-
} else
8496-
promotion_qual_type = enum_decl->getIntegerType();
8486+
clang::QualType BestPromotionType;
8487+
clang::QualType BestType;
8488+
ast.computeBestEnumTypes(/*IsPacked=*/false, NumNegativeBits,
8489+
NumPositiveBits, BestType, BestPromotionType);
84978490

84988491
enum_decl->completeDefinition(enum_decl->getIntegerType(),
8499-
promotion_qual_type, NumPositiveBits,
8492+
BestPromotionType, NumPositiveBits,
85008493
NumNegativeBits);
85018494
}
85028495
return true;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
CXX_SOURCES := main.cpp
2+
3+
include Makefile.rules
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
"""
2+
Test LLDB type promotion of unscoped enums.
3+
"""
4+
5+
import lldb
6+
from lldbsuite.test.decorators import *
7+
from lldbsuite.test.lldbtest import *
8+
from lldbsuite.test import lldbutil
9+
10+
11+
class TestCPPEnumPromotion(TestBase):
12+
def test(self):
13+
self.build()
14+
lldbutil.run_to_source_breakpoint(
15+
self, "// break here", lldb.SBFileSpec("main.cpp")
16+
)
17+
UChar_promoted = self.frame().FindVariable("UChar_promoted")
18+
UShort_promoted = self.frame().FindVariable("UShort_promoted")
19+
UInt_promoted = self.frame().FindVariable("UInt_promoted")
20+
SLong_promoted = self.frame().FindVariable("SLong_promoted")
21+
ULong_promoted = self.frame().FindVariable("ULong_promoted")
22+
NChar_promoted = self.frame().FindVariable("NChar_promoted")
23+
NShort_promoted = self.frame().FindVariable("NShort_promoted")
24+
NInt_promoted = self.frame().FindVariable("NInt_promoted")
25+
NLong_promoted = self.frame().FindVariable("NLong_promoted")
26+
27+
# Check that LLDB's promoted type is the same as the compiler's
28+
self.expect_expr("+EnumUChar::UChar", result_type=UChar_promoted.type.name)
29+
self.expect_expr("+EnumUShort::UShort", result_type=UShort_promoted.type.name)
30+
self.expect_expr("+EnumUInt::UInt", result_type=UInt_promoted.type.name)
31+
self.expect_expr("+EnumSLong::SLong", result_type=SLong_promoted.type.name)
32+
self.expect_expr("+EnumULong::ULong", result_type=ULong_promoted.type.name)
33+
self.expect_expr("+EnumNChar::NChar", result_type=NChar_promoted.type.name)
34+
self.expect_expr("+EnumNShort::NShort", result_type=NShort_promoted.type.name)
35+
self.expect_expr("+EnumNInt::NInt", result_type=NInt_promoted.type.name)
36+
self.expect_expr("+EnumNLong::NLong", result_type=NLong_promoted.type.name)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
enum EnumUChar { UChar = 1 };
2+
enum EnumUShort { UShort = 0x101 };
3+
enum EnumUInt { UInt = 0x10001 };
4+
enum EnumSLong { SLong = 0x100000001 };
5+
enum EnumULong { ULong = 0xFFFFFFFFFFFFFFF0 };
6+
enum EnumNChar { NChar = -1 };
7+
enum EnumNShort { NShort = -0x101 };
8+
enum EnumNInt { NInt = -0x10001 };
9+
enum EnumNLong { NLong = -0x100000001 };
10+
11+
int main() {
12+
auto UChar_promoted = +EnumUChar::UChar;
13+
auto UShort_promoted = +EnumUShort::UShort;
14+
auto UInt_promoted = +EnumUInt::UInt;
15+
auto SLong_promoted = +EnumSLong::SLong;
16+
auto ULong_promoted = +EnumULong::ULong;
17+
auto NChar_promoted = +EnumNChar::NChar;
18+
auto NShort_promoted = +EnumNShort::NShort;
19+
auto NInt_promoted = +EnumNInt::NInt;
20+
auto NLong_promoted = +EnumNLong::NLong;
21+
return 0; // break here
22+
}

0 commit comments

Comments
 (0)