diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -537,6 +537,13 @@ Opts.ModulesLocalVisibility = 1; } +static QualType desugarType(QualType type) { + while (const clang::ElaboratedType *elaboratedType = + llvm::dyn_cast(type)) + type = elaboratedType->desugar(); + return type; +} + TypeSystemClang::TypeSystemClang(llvm::StringRef name, llvm::Triple target_triple) { m_display_name = name.str(); @@ -3539,7 +3546,7 @@ bool TypeSystemClang::IsTypedefType(lldb::opaque_compiler_type_t type) { if (!type) return false; - return GetQualType(type)->getTypeClass() == clang::Type::Typedef; + return desugarType(GetQualType(type))->getTypeClass() == clang::Type::Typedef; } bool TypeSystemClang::IsVoidType(lldb::opaque_compiler_type_t type) { @@ -4524,7 +4531,7 @@ TypeSystemClang::GetTypedefedType(lldb::opaque_compiler_type_t type) { if (type) { const clang::TypedefType *typedef_type = - llvm::dyn_cast(GetQualType(type)); + llvm::dyn_cast(desugarType(GetQualType(type))); if (typedef_type) return GetType(typedef_type->getDecl()->getUnderlyingType()); } diff --git a/lldb/test/API/lang/cpp/typedef/Makefile b/lldb/test/API/lang/cpp/typedef/Makefile new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/cpp/typedef/Makefile @@ -0,0 +1,2 @@ +CXX_SOURCES := main.cpp +include Makefile.rules diff --git a/lldb/test/API/lang/cpp/typedef/TestCppTypedef.py b/lldb/test/API/lang/cpp/typedef/TestCppTypedef.py new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/cpp/typedef/TestCppTypedef.py @@ -0,0 +1,55 @@ +""" +Test that we can retrieve typedefed types correctly +""" + + + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * +from lldbsuite.test import decorators + +class TestCppTypedef(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_typedef(self): + """ + Test that we retrieve typedefed types correctly + """ + + # Build and run until the breakpoint + self.build() + self.main_source_file = lldb.SBFileSpec("main.cpp") + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( + self, "Set a breakpoint here", self.main_source_file) + + # Get the current frame + frame = thread.GetSelectedFrame() + + # First of all, check that we can get a typedefed type correctly in a simple case + + expr_result = frame.EvaluateExpression("(SF)s") + self.assertTrue(expr_result.IsValid(), "Can't evaluate an expression with result type `SF`") + + typedef_type = expr_result.GetType(); + self.assertTrue(typedef_type.IsValid(), "Can't get `SF` type of evaluated expression") + self.assertTrue(typedef_type.IsTypedefType(), "Type `SF` should be a typedef") + + typedefed_type = typedef_type.GetTypedefedType() + self.assertTrue(typedefed_type.IsValid(), "Can't get `SF` typedefed type") + self.assertEqual(typedefed_type.GetName(), "S", "Got invalid `SF` typedefed type") + + # Check that we can get a typedefed type correctly in the case + # when an elaborated type is created during the parsing + + expr_result = frame.EvaluateExpression("(SF::V)s.value") + self.assertTrue(expr_result.IsValid(), "Can't evaluate an expression with result type `SF::V`") + + typedef_type = expr_result.GetType(); + self.assertTrue(typedef_type.IsValid(), "Can't get `SF::V` type of evaluated expression") + self.assertTrue(typedef_type.IsTypedefType(), "Type `SF::V` should be a typedef") + + typedefed_type = typedef_type.GetTypedefedType() + self.assertTrue(typedefed_type.IsValid(), "Can't get `SF::V` typedefed type") + self.assertEqual(typedefed_type.GetName(), "float", "Got invalid `SF::V` typedefed type") diff --git a/lldb/test/API/lang/cpp/typedef/main.cpp b/lldb/test/API/lang/cpp/typedef/main.cpp new file mode 100644 --- /dev/null +++ b/lldb/test/API/lang/cpp/typedef/main.cpp @@ -0,0 +1,13 @@ +template +struct S { + typedef T V; + + V value; +}; + +typedef S SF; + +int main (int argc, char const *argv[]) { + SF s{ .5 }; + return 0; // Set a breakpoint here +}