Skip to content

Conversation

@Michael137
Copy link
Member

SBType::GetBasicType fails on typedefs to primitive types. The docs for GetBasicType state:

Returns the BasicType value that is most appropriate to this type

But, e.g., for uint64_t this would currently return eBasicTypeInvalid.

TypeSystemClang::GetBasicTypeEnumeration (which is what SBType::GetBasicType uses) doesn't see through typedefs. Inside LLDB we almost always call GetBasicTypeEnumeration on the canonical type. In the cases we don't I suspect those were just subtle bugs. This patch gets the canonical type inside of GetBasicTypeEnumeration instead.

rdar://155829208

`SBType::GetBasicType` fails on typedefs to primitive types. The docs for `GetBasicType` state:
```
Returns the BasicType value that is most appropriate to this type
```
But, e.g., for `uint64_t` this would currently return `eBasicTypeInvalid`.

`TypeSystemClang::GetBasicTypeEnumeration` (which is what
`SBType::GetBasicType` uses) doesn't see through typedefs.
Inside LLDB we almost always call `GetBasicTypeEnumeration`
on the canonical type. In the cases we don't I suspect those were just
subtle bugs. This patch gets the canonical type inside of
`GetBasicTypeEnumeration` instead.

rdar://155829208
@Michael137 Michael137 requested a review from labath July 16, 2025 15:07
@Michael137 Michael137 requested a review from JDevlieghere as a code owner July 16, 2025 15:07
@llvmbot llvmbot added the lldb label Jul 16, 2025
@llvmbot
Copy link
Member

llvmbot commented Jul 16, 2025

@llvm/pr-subscribers-lldb

Author: Michael Buch (Michael137)

Changes

SBType::GetBasicType fails on typedefs to primitive types. The docs for GetBasicType state:

Returns the BasicType value that is most appropriate to this type

But, e.g., for uint64_t this would currently return eBasicTypeInvalid.

TypeSystemClang::GetBasicTypeEnumeration (which is what SBType::GetBasicType uses) doesn't see through typedefs. Inside LLDB we almost always call GetBasicTypeEnumeration on the canonical type. In the cases we don't I suspect those were just subtle bugs. This patch gets the canonical type inside of GetBasicTypeEnumeration instead.

rdar://155829208


Full diff: https://github.com/llvm/llvm-project/pull/149112.diff

6 Files Affected:

  • (modified) lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp (+1-1)
  • (modified) lldb/source/Symbol/CompilerType.cpp (+4-6)
  • (modified) lldb/source/ValueObject/ValueObject.cpp (+4-4)
  • (added) lldb/test/API/python_api/sbtype_basic_type/Makefile (+3)
  • (added) lldb/test/API/python_api/sbtype_basic_type/TestSBTypeBasicType.py (+32)
  • (added) lldb/test/API/python_api/sbtype_basic_type/main.cpp (+11)
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 82e07bb8e0ffb..216d5a9f4745f 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -5467,7 +5467,7 @@ CompilerType TypeSystemClang::GetBuiltinTypeByName(ConstString name) {
 lldb::BasicType
 TypeSystemClang::GetBasicTypeEnumeration(lldb::opaque_compiler_type_t type) {
   if (type) {
-    clang::QualType qual_type(GetQualType(type));
+    clang::QualType qual_type(GetCanonicalQualType(type));
     const clang::Type::TypeClass type_class = qual_type->getTypeClass();
     if (type_class == clang::Type::Builtin) {
       switch (llvm::cast<clang::BuiltinType>(qual_type)->getKind()) {
diff --git a/lldb/source/Symbol/CompilerType.cpp b/lldb/source/Symbol/CompilerType.cpp
index dd81fc2361f88..62c0ddf51c012 100644
--- a/lldb/source/Symbol/CompilerType.cpp
+++ b/lldb/source/Symbol/CompilerType.cpp
@@ -354,12 +354,11 @@ bool CompilerType::IsSigned() const {
 }
 
 bool CompilerType::IsNullPtrType() const {
-  return GetCanonicalType().GetBasicTypeEnumeration() ==
-         lldb::eBasicTypeNullPtr;
+  return GetBasicTypeEnumeration() == lldb::eBasicTypeNullPtr;
 }
 
 bool CompilerType::IsBoolean() const {
-  return GetCanonicalType().GetBasicTypeEnumeration() == lldb::eBasicTypeBool;
+  return GetBasicTypeEnumeration() == lldb::eBasicTypeBool;
 }
 
 bool CompilerType::IsEnumerationIntegerTypeSigned() const {
@@ -379,7 +378,7 @@ bool CompilerType::IsPromotableIntegerType() const {
   if (IsUnscopedEnumerationType())
     return true;
 
-  switch (GetCanonicalType().GetBasicTypeEnumeration()) {
+  switch (GetBasicTypeEnumeration()) {
   case lldb::eBasicTypeBool:
   case lldb::eBasicTypeChar:
   case lldb::eBasicTypeSignedChar:
@@ -455,8 +454,7 @@ bool CompilerType::IsContextuallyConvertibleToBool() const {
 }
 
 bool CompilerType::IsBasicType() const {
-  return GetCanonicalType().GetBasicTypeEnumeration() !=
-         lldb::eBasicTypeInvalid;
+  return GetBasicTypeEnumeration() != lldb::eBasicTypeInvalid;
 }
 
 std::string CompilerType::TypeDescription() {
diff --git a/lldb/source/ValueObject/ValueObject.cpp b/lldb/source/ValueObject/ValueObject.cpp
index a6fb3fad65251..84ad130299221 100644
--- a/lldb/source/ValueObject/ValueObject.cpp
+++ b/lldb/source/ValueObject/ValueObject.cpp
@@ -3228,8 +3228,8 @@ lldb::ValueObjectSP ValueObject::CastToBasicType(CompilerType type) {
         llvm::APSInt ext =
             int_value_or_err->extOrTrunc(type_byte_size * CHAR_BIT);
         Scalar scalar_int(ext);
-        llvm::APFloat f = scalar_int.CreateAPFloatFromAPSInt(
-            type.GetCanonicalType().GetBasicTypeEnumeration());
+        llvm::APFloat f =
+            scalar_int.CreateAPFloatFromAPSInt(type.GetBasicTypeEnumeration());
         return ValueObject::CreateValueObjectFromAPFloat(target, f, type,
                                                          "result");
       } else {
@@ -3245,7 +3245,7 @@ lldb::ValueObjectSP ValueObject::CastToBasicType(CompilerType type) {
         if (int_value_or_err) {
           Scalar scalar_int(*int_value_or_err);
           llvm::APFloat f = scalar_int.CreateAPFloatFromAPSInt(
-              type.GetCanonicalType().GetBasicTypeEnumeration());
+              type.GetBasicTypeEnumeration());
           return ValueObject::CreateValueObjectFromAPFloat(target, f, type,
                                                            "result");
         } else {
@@ -3261,7 +3261,7 @@ lldb::ValueObjectSP ValueObject::CastToBasicType(CompilerType type) {
         if (float_value_or_err) {
           Scalar scalar_float(*float_value_or_err);
           llvm::APFloat f = scalar_float.CreateAPFloatFromAPFloat(
-              type.GetCanonicalType().GetBasicTypeEnumeration());
+              type.GetBasicTypeEnumeration());
           return ValueObject::CreateValueObjectFromAPFloat(target, f, type,
                                                            "result");
         } else {
diff --git a/lldb/test/API/python_api/sbtype_basic_type/Makefile b/lldb/test/API/python_api/sbtype_basic_type/Makefile
new file mode 100644
index 0000000000000..99998b20bcb05
--- /dev/null
+++ b/lldb/test/API/python_api/sbtype_basic_type/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git a/lldb/test/API/python_api/sbtype_basic_type/TestSBTypeBasicType.py b/lldb/test/API/python_api/sbtype_basic_type/TestSBTypeBasicType.py
new file mode 100644
index 0000000000000..ba74341324039
--- /dev/null
+++ b/lldb/test/API/python_api/sbtype_basic_type/TestSBTypeBasicType.py
@@ -0,0 +1,32 @@
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TestCase(TestBase):
+    def test(self):
+        """Test that SBType.GetBasicType unwraps typedefs."""
+        self.build()
+        lldbutil.run_to_source_breakpoint(
+            self, "return", lldb.SBFileSpec("main.cpp")
+        )
+
+        a = self.frame().FindVariable("a")
+        self.assertTrue(a)
+
+        int_basic_type = a.GetType().GetBasicType()
+        self.assertEqual(int_basic_type, 13)
+
+        b = self.frame().FindVariable("b")
+        self.assertTrue(b)
+
+        c = self.frame().FindVariable("c")
+        self.assertTrue(c)
+
+        d = self.frame().FindVariable("d")
+        self.assertTrue(d)
+
+        self.assertEqual(a.GetType().GetBasicType(), int_basic_type)
+        self.assertEqual(b.GetType().GetBasicType(), int_basic_type)
+        self.assertEqual(c.GetType().GetBasicType(), int_basic_type)
diff --git a/lldb/test/API/python_api/sbtype_basic_type/main.cpp b/lldb/test/API/python_api/sbtype_basic_type/main.cpp
new file mode 100644
index 0000000000000..7ded37186edaf
--- /dev/null
+++ b/lldb/test/API/python_api/sbtype_basic_type/main.cpp
@@ -0,0 +1,11 @@
+using T1 = int;
+using T2 = T1;
+using T3 = T2;
+
+int main() {
+  int a;
+  T1 b;
+  T2 c;
+  T3 d;
+  return 0;
+}

@Michael137 Michael137 requested a review from adrian-prantl July 22, 2025 14:30
@Michael137 Michael137 merged commit b7889a6 into llvm:main Jul 23, 2025
9 checks passed
@Michael137 Michael137 deleted the lldb/basic-type-canonical branch July 23, 2025 07:52
Michael137 added a commit to swiftlang/llvm-project that referenced this pull request Jul 25, 2025
`SBType::GetBasicType` fails on typedefs to primitive types. The docs
for `GetBasicType` state:
```
Returns the BasicType value that is most appropriate to this type
```
But, e.g., for `uint64_t` this would currently return
`eBasicTypeInvalid`.

`TypeSystemClang::GetBasicTypeEnumeration` (which is what
`SBType::GetBasicType` uses) doesn't see through typedefs. Inside LLDB
we almost always call `GetBasicTypeEnumeration` on the canonical type.
In the cases we don't I suspect those were just subtle bugs. This patch
gets the canonical type inside of `GetBasicTypeEnumeration` instead.

rdar://155829208
(cherry picked from commit b7889a6)
mahesh-attarde pushed a commit to mahesh-attarde/llvm-project that referenced this pull request Jul 28, 2025
`SBType::GetBasicType` fails on typedefs to primitive types. The docs
for `GetBasicType` state:
```
Returns the BasicType value that is most appropriate to this type
```
But, e.g., for `uint64_t` this would currently return
`eBasicTypeInvalid`.

`TypeSystemClang::GetBasicTypeEnumeration` (which is what
`SBType::GetBasicType` uses) doesn't see through typedefs. Inside LLDB
we almost always call `GetBasicTypeEnumeration` on the canonical type.
In the cases we don't I suspect those were just subtle bugs. This patch
gets the canonical type inside of `GetBasicTypeEnumeration` instead.

rdar://155829208
augusto2112 pushed a commit to augusto2112/llvm-project that referenced this pull request Aug 15, 2025
`SBType::GetBasicType` fails on typedefs to primitive types. The docs
for `GetBasicType` state:
```
Returns the BasicType value that is most appropriate to this type
```
But, e.g., for `uint64_t` this would currently return
`eBasicTypeInvalid`.

`TypeSystemClang::GetBasicTypeEnumeration` (which is what
`SBType::GetBasicType` uses) doesn't see through typedefs. Inside LLDB
we almost always call `GetBasicTypeEnumeration` on the canonical type.
In the cases we don't I suspect those were just subtle bugs. This patch
gets the canonical type inside of `GetBasicTypeEnumeration` instead.

rdar://155829208
(cherry picked from commit b7889a6)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants