Michael137 created this revision. Michael137 added reviewers: aprantl, jingham, werat, labath. Herald added a project: All. Michael137 requested review of this revision. Herald added a project: LLDB. Herald added a subscriber: lldb-commits.
`IntegerLiteral::Create` expects integer types. For that reason when we parse DWARF into an AST, when we encounter a constant initialized enum member variable, we try to determine the underlying integer type before creating the `IntegerLiteral`. However, we currently don't desugar the type and the `dyn_cast<EnumType>` fails. In debug builds this triggers following assert: Assertion failed: (type->isIntegerType() && "Illegal type in IntegerLiteral"), function IntegerLiteral, file Expr.cpp, line 892 This patch turns the `dyn_cast<EnumType>` into a `getAs<EnumType>` which desguars the enum if necessary, allowing us to get to the underlying integer type. **Testing** - API test - Manual repro is fixed Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D130213 Files: lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp lldb/test/API/lang/cpp/const_static_integral_member/TestConstStaticIntegralMember.py lldb/test/API/lang/cpp/const_static_integral_member/main.cpp Index: lldb/test/API/lang/cpp/const_static_integral_member/main.cpp =================================================================== --- lldb/test/API/lang/cpp/const_static_integral_member/main.cpp +++ lldb/test/API/lang/cpp/const_static_integral_member/main.cpp @@ -1,3 +1,4 @@ +#include <cstdint> #include <limits> enum Enum { @@ -69,6 +70,11 @@ constexpr static ScopedEnum scoped_enum_val = ScopedEnum::scoped_enum_case2; } cwc; +struct ClassWithEnumAlias { + using EnumAlias = ScopedEnum; + static constexpr EnumAlias enum_alias = ScopedEnum::scoped_enum_case2; +}; + int main() { A a; @@ -98,5 +104,8 @@ se = A::invalid_scoped_enum_val; ScopedCharEnum sce = A::scoped_char_enum_val; ScopedLongLongEnum sle = A::scoped_ll_enum_val; + + auto enum_alias_val = ClassWithEnumAlias::enum_alias; + return 0; // break here } Index: lldb/test/API/lang/cpp/const_static_integral_member/TestConstStaticIntegralMember.py =================================================================== --- lldb/test/API/lang/cpp/const_static_integral_member/TestConstStaticIntegralMember.py +++ lldb/test/API/lang/cpp/const_static_integral_member/TestConstStaticIntegralMember.py @@ -66,6 +66,9 @@ self.expect_expr("A::scoped_ll_enum_val_neg", result_value="case0") self.expect_expr("A::scoped_ll_enum_val", result_value="case2") + # Test an aliased enum with fixed underlying type. + self.expect_expr("ClassWithEnumAlias::enum_alias", result_value="scoped_enum_case2") + # Test taking address. if lldbplatformutil.getPlatform() == "windows": # On Windows data members without the out-of-class definitions still have Index: lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp =================================================================== --- lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -7538,10 +7538,11 @@ "only integer or enum types supported"); // If the variable is an enum type, take the underlying integer type as // the type of the integer literal. - if (const EnumType *enum_type = llvm::dyn_cast<EnumType>(qt.getTypePtr())) { + if (const EnumType *enum_type = qt->getAs<EnumType>()) { const EnumDecl *enum_decl = enum_type->getDecl(); qt = enum_decl->getIntegerType(); } + var->setInit(IntegerLiteral::Create(ast, init_value, qt.getUnqualifiedType(), SourceLocation())); }
Index: lldb/test/API/lang/cpp/const_static_integral_member/main.cpp =================================================================== --- lldb/test/API/lang/cpp/const_static_integral_member/main.cpp +++ lldb/test/API/lang/cpp/const_static_integral_member/main.cpp @@ -1,3 +1,4 @@ +#include <cstdint> #include <limits> enum Enum { @@ -69,6 +70,11 @@ constexpr static ScopedEnum scoped_enum_val = ScopedEnum::scoped_enum_case2; } cwc; +struct ClassWithEnumAlias { + using EnumAlias = ScopedEnum; + static constexpr EnumAlias enum_alias = ScopedEnum::scoped_enum_case2; +}; + int main() { A a; @@ -98,5 +104,8 @@ se = A::invalid_scoped_enum_val; ScopedCharEnum sce = A::scoped_char_enum_val; ScopedLongLongEnum sle = A::scoped_ll_enum_val; + + auto enum_alias_val = ClassWithEnumAlias::enum_alias; + return 0; // break here } Index: lldb/test/API/lang/cpp/const_static_integral_member/TestConstStaticIntegralMember.py =================================================================== --- lldb/test/API/lang/cpp/const_static_integral_member/TestConstStaticIntegralMember.py +++ lldb/test/API/lang/cpp/const_static_integral_member/TestConstStaticIntegralMember.py @@ -66,6 +66,9 @@ self.expect_expr("A::scoped_ll_enum_val_neg", result_value="case0") self.expect_expr("A::scoped_ll_enum_val", result_value="case2") + # Test an aliased enum with fixed underlying type. + self.expect_expr("ClassWithEnumAlias::enum_alias", result_value="scoped_enum_case2") + # Test taking address. if lldbplatformutil.getPlatform() == "windows": # On Windows data members without the out-of-class definitions still have Index: lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp =================================================================== --- lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -7538,10 +7538,11 @@ "only integer or enum types supported"); // If the variable is an enum type, take the underlying integer type as // the type of the integer literal. - if (const EnumType *enum_type = llvm::dyn_cast<EnumType>(qt.getTypePtr())) { + if (const EnumType *enum_type = qt->getAs<EnumType>()) { const EnumDecl *enum_decl = enum_type->getDecl(); qt = enum_decl->getIntegerType(); } + var->setInit(IntegerLiteral::Create(ast, init_value, qt.getUnqualifiedType(), SourceLocation())); }
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits