Skip to content

[lldb] Print "0x0" for bitfield like enums where the value is 0 #97557

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 3, 2024

Conversation

DavidSpickett
Copy link
Collaborator

Enums like this one are treated as bitfield like enums: enum FlagsLike {B=2, C=4};

lldb recognises them as collections of flags, so you can have "B | C". If there's any values not covered that's printed as hex "B | C | 0x1".

What happened if the value was 0 was we would not match any of the enumerators, then the remainder check requires that the remainder is non-zero. So lldb would print nothing at all.

Which I assume is a bug because knowing that no flags are set is useful, just as much as knowing that some unkown bit was set to make it non-zero.

Enums like this one are treated as bitfield like enums:
enum FlagsLike {B=2, C=4};

lldb recognises them as collections of flags, so you can have
"B | C". If there's any values not covered that's printed
as hex "B | C | 0x1".

What happened if the value was 0 was we would not match any
of the enumerators, then the remainder check requires that
the remainder is non-zero. So lldb would print nothing at all.

Which I assume is a bug because knowing that no flags are set
is useful, just as much as knowing that some unkown bit was set
to make it non-zero.
@llvmbot llvmbot added the lldb label Jul 3, 2024
@DavidSpickett DavidSpickett requested a review from clayborg July 3, 2024 11:22
@llvmbot
Copy link
Member

llvmbot commented Jul 3, 2024

@llvm/pr-subscribers-lldb

Author: David Spickett (DavidSpickett)

Changes

Enums like this one are treated as bitfield like enums: enum FlagsLike {B=2, C=4};

lldb recognises them as collections of flags, so you can have "B | C". If there's any values not covered that's printed as hex "B | C | 0x1".

What happened if the value was 0 was we would not match any of the enumerators, then the remainder check requires that the remainder is non-zero. So lldb would print nothing at all.

Which I assume is a bug because knowing that no flags are set is useful, just as much as knowing that some unkown bit was set to make it non-zero.


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

2 Files Affected:

  • (modified) lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp (+9-1)
  • (modified) lldb/unittests/ValueObject/DumpValueObjectOptionsTests.cpp (+3-3)
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 093d27a92d718..560b042c75bb7 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -8680,6 +8680,13 @@ static bool DumpEnumValue(const clang::QualType &qual_type, Stream &s,
     return true;
   }
 
+  if (!enum_uvalue) {
+    // This is a bitfield enum, but the value is 0 so we know it won't match
+    // with any of the enumerators.
+    s.Printf("0x%" PRIx64, enum_uvalue);
+    return true;
+  }
+
   uint64_t remaining_value = enum_uvalue;
   std::vector<std::pair<uint64_t, llvm::StringRef>> values;
   values.reserve(num_enumerators);
@@ -8704,7 +8711,8 @@ static bool DumpEnumValue(const clang::QualType &qual_type, Stream &s,
       s.PutCString(" | ");
   }
 
-  // If there is a remainder that is not covered by the value, print it as hex.
+  // If there is a remainder that is not covered by the value, print it as
+  // hex.
   if (remaining_value)
     s.Printf("0x%" PRIx64, remaining_value);
 
diff --git a/lldb/unittests/ValueObject/DumpValueObjectOptionsTests.cpp b/lldb/unittests/ValueObject/DumpValueObjectOptionsTests.cpp
index 6cb982d7f5980..a7ccd74721f66 100644
--- a/lldb/unittests/ValueObject/DumpValueObjectOptionsTests.cpp
+++ b/lldb/unittests/ValueObject/DumpValueObjectOptionsTests.cpp
@@ -149,12 +149,12 @@ TEST_F(ValueObjectMockProcessTest, Enum) {
 TEST_F(ValueObjectMockProcessTest, BitFieldLikeEnum) {
   // These enumerators set individual bits in the value, as if it were a flag
   // set. lldb treats this as a "bitfield like enum". This means we show values
-  // as hex, a value of 0 shows nothing, and values with no exact enumerator are
-  // shown as combinations of the other values.
+  // as hex, and values without exact matches are shown as a combination of
+  // enumerators and any remaining value left over.
   TestDumpValueObject(
       MakeEnumType({{"test_2", 2}, {"test_4", 4}}),
       {
-          {0, {}, "(TestEnum) test_var =\n"},
+          {0, {}, "(TestEnum) test_var = 0x0\n"},
           {1, {}, "(TestEnum) test_var = 0x1\n"},
           {2, {}, "(TestEnum) test_var = test_2\n"},
           {4, {}, "(TestEnum) test_var = test_4\n"},

@DavidSpickett
Copy link
Collaborator Author

There is a comment in this function:

  // Try to find an exact match for the value.
  // At the same time, we're applying a heuristic to determine whether we want
  // to print this enum as a bitfield. We're likely dealing with a bitfield if
  // every enumerator is either a one bit value or a superset of the previous
  // enumerators. Also 0 doesn't make sense when the enumerators are used as
  // flags.

The last sentence is ambiguous, but I think it refers to enumerators of 0, not the value being 0. If I'm wrong, I haven't found any other clues as to why printing nothing for a value of 0x0 makes sense. I think it's just an oversight.

Copy link
Member

@Michael137 Michael137 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@DavidSpickett DavidSpickett merged commit 3101524 into llvm:main Jul 3, 2024
8 checks passed
@DavidSpickett DavidSpickett deleted the lldb-bitenum branch July 3, 2024 13:48
lravenclaw pushed a commit to lravenclaw/llvm-project that referenced this pull request Jul 3, 2024
…#97557)

Enums like this one are treated as bitfield like enums: enum FlagsLike
{B=2, C=4};

lldb recognises them as collections of flags, so you can have "B | C".
If there's any values not covered that's printed as hex "B | C | 0x1".

What happened if the value was 0 was we would not match any of the
enumerators, then the remainder check requires that the remainder is
non-zero. So lldb would print nothing at all.

Which I assume is a bug because knowing that no flags are set is useful,
just as much as knowing that some unkown bit was set to make it
non-zero.
kbluck pushed a commit to kbluck/llvm-project that referenced this pull request Jul 6, 2024
…#97557)

Enums like this one are treated as bitfield like enums: enum FlagsLike
{B=2, C=4};

lldb recognises them as collections of flags, so you can have "B | C".
If there's any values not covered that's printed as hex "B | C | 0x1".

What happened if the value was 0 was we would not match any of the
enumerators, then the remainder check requires that the remainder is
non-zero. So lldb would print nothing at all.

Which I assume is a bug because knowing that no flags are set is useful,
just as much as knowing that some unkown bit was set to make it
non-zero.
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