[clang] Fix evaluation of the unsigned enumeration values, #108766 (PR #108769)

Dmitry Fursov via cfe-commits cfe-commits at lists.llvm.org
Tue Sep 17 10:11:59 PDT 2024


https://github.com/fursov updated https://github.com/llvm/llvm-project/pull/108769

>From 4d9f2e2e9ac57b4279a4aafc078a3b4fb3ff646f Mon Sep 17 00:00:00 2001
From: Dmitry Fursov <dfoursov at yahoo.com>
Date: Sun, 15 Sep 2024 18:14:48 +0300
Subject: [PATCH] Fix evaluation of the unsigned enumeration values

If the type of an enumeration is not native (e.g. uint8_t) but
is unsigned then evaluation of the value might get wrong: for
values bigger than half of type range the return value will be
negative. This happens because for non-native enum types the TypeKind
is ELABORATED. To get the real integer type, the conversion to
canonical type is required before the enum_value() function can
decide about type being signed or unsigned.
---
 clang/bindings/python/clang/cindex.py         |  2 ++
 .../python/tests/cindex/test_cursor.py        | 20 +++++++++++++++++++
 2 files changed, 22 insertions(+)

diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index 4da99e899e7f7c..c582c82ce50789 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -1952,6 +1952,8 @@ def enum_value(self):
             underlying_type = self.type
             if underlying_type.kind == TypeKind.ENUM:
                 underlying_type = underlying_type.get_declaration().enum_type
+            if underlying_type.kind == TypeKind.ELABORATED:
+                underlying_type = underlying_type.get_canonical()
             if underlying_type.kind in (
                 TypeKind.CHAR_U,
                 TypeKind.UCHAR,
diff --git a/clang/bindings/python/tests/cindex/test_cursor.py b/clang/bindings/python/tests/cindex/test_cursor.py
index 7476947bde2ea6..927e35993a1c37 100644
--- a/clang/bindings/python/tests/cindex/test_cursor.py
+++ b/clang/bindings/python/tests/cindex/test_cursor.py
@@ -570,6 +570,26 @@ def test_enum_values_cpp(self):
         self.assertEqual(ham.kind, CursorKind.ENUM_CONSTANT_DECL)
         self.assertEqual(ham.enum_value, 0x10000000000)
 
+    def test_enum_values_on_elaborated_type(self):
+        tu = get_tu(
+            "using myUType = unsigned char; enum TEST : myUType { SPAM = 1, HAM = 0xff; }",
+            lang="cpp",
+        )
+        enum = get_cursor(tu, "TEST")
+        self.assertIsNotNone(enum)
+
+        self.assertEqual(enum.kind, CursorKind.ENUM_DECL)
+
+        enum_constants = list(enum.get_children())
+        self.assertEqual(len(enum_constants), 2)
+
+        spam, ham = enum_constants
+
+        self.assertEqual(spam.kind, CursorKind.ENUM_CONSTANT_DECL)
+        self.assertEqual(spam.enum_value, 1)
+        self.assertEqual(ham.kind, CursorKind.ENUM_CONSTANT_DECL)
+        self.assertEqual(ham.enum_value, 255)
+
     def test_annotation_attribute(self):
         tu = get_tu(
             'int foo (void) __attribute__ ((annotate("here be annotation attribute")));'



More information about the cfe-commits mailing list