https://github.com/MythreyaK updated 
https://github.com/llvm/llvm-project/pull/173187

>From e23269bbf04f18883a000b6e647fe7795ce86489 Mon Sep 17 00:00:00 2001
From: Mythreya <[email protected]>
Date: Sun, 21 Dec 2025 05:00:58 -0800
Subject: [PATCH 1/3] [clangd] Fix crash on hover over large `UL` enums

---
 clang-tools-extra/clangd/Hover.cpp            |  4 +-
 .../clangd/unittests/HoverTests.cpp           | 59 +++++++++++++++++++
 2 files changed, 61 insertions(+), 2 deletions(-)

diff --git a/clang-tools-extra/clangd/Hover.cpp 
b/clang-tools-extra/clangd/Hover.cpp
index 34369e188d4ec..7ec7e6d19105a 100644
--- a/clang-tools-extra/clangd/Hover.cpp
+++ b/clang-tools-extra/clangd/Hover.cpp
@@ -451,7 +451,7 @@ std::optional<std::string> printExprValue(const Expr *E,
 
   // Show enums symbolically, not numerically like APValue::printPretty().
   if (T->isEnumeralType() && Constant.Val.isInt() &&
-      Constant.Val.getInt().getSignificantBits() <= 64) {
+      Constant.Val.getInt().isRepresentableByInt64()) {
     // Compare to int64_t to avoid bit-width match requirements.
     int64_t Val = Constant.Val.getInt().getExtValue();
     for (const EnumConstantDecl *ECD : T->castAsEnumDecl()->enumerators())
@@ -462,7 +462,7 @@ std::optional<std::string> printExprValue(const Expr *E,
   }
   // Show hex value of integers if they're at least 10 (or negative!)
   if (T->isIntegralOrEnumerationType() && Constant.Val.isInt() &&
-      Constant.Val.getInt().getSignificantBits() <= 64 &&
+      Constant.Val.getInt().isRepresentableByInt64() &&
       Constant.Val.getInt().uge(10))
     return llvm::formatv("{0} ({1})", Constant.Val.getAsString(Ctx, T),
                          printHex(Constant.Val.getInt()))
diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp 
b/clang-tools-extra/clangd/unittests/HoverTests.cpp
index eb858ff616e90..0c8423bd5fb2a 100644
--- a/clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -5015,6 +5015,65 @@ TEST(Hover, FunctionParameters) {
   }
 }
 
+TEST(Hover, GH2381) {
+  Annotations Code(R"cpp(
+  struct Foo {
+    enum Bar {
+      A = -42UL,
+      B = ~0UL,
+      C = 0xFFFFFFFFFFFFFFFFUL,
+    };
+  };
+  constexpr auto va$a^ = Foo::A;
+  constexpr auto vb$b^ = Foo::B;
+  constexpr auto vc$c^ = Foo::C;
+  )cpp");
+
+  TestTU TU = TestTU::withCode(Code.code());
+  auto AST = TU.build();
+
+  {
+    auto H = getHover(AST, Code.point("a"), format::getLLVMStyle(), nullptr);
+
+    ASSERT_TRUE(H);
+    EXPECT_EQ(H->Name, "va");
+    EXPECT_EQ(H->Kind, index::SymbolKind::Variable);
+    EXPECT_EQ(H->NamespaceScope, "");
+    EXPECT_EQ(H->LocalScope, "");
+    EXPECT_EQ(H->Type, "const Foo::Bar");
+    EXPECT_EQ(H->Definition, "constexpr auto va = Foo::A");
+    // FIXME: Should be "A (FFFFFFFFFFFFFFD6)
+    EXPECT_EQ(H->Value, "18446744073709551574");
+  }
+
+  {
+    auto H = getHover(AST, Code.point("b"), format::getLLVMStyle(), nullptr);
+
+    ASSERT_TRUE(H);
+    EXPECT_EQ(H->Name, "vb");
+    EXPECT_EQ(H->Kind, index::SymbolKind::Variable);
+    EXPECT_EQ(H->NamespaceScope, "");
+    EXPECT_EQ(H->LocalScope, "");
+    EXPECT_EQ(H->Type, "const Foo::Bar");
+    EXPECT_EQ(H->Definition, "constexpr auto vb = Foo::B");
+    // FIXME: Should be "B (0xFFFFFFFFFFFFFFFF)");
+    EXPECT_EQ(H->Value, "18446744073709551615");
+  }
+
+  {
+    auto H = getHover(AST, Code.point("c"), format::getLLVMStyle(), nullptr);
+
+    ASSERT_TRUE(H);
+    EXPECT_EQ(H->Name, "vc");
+    EXPECT_EQ(H->Kind, index::SymbolKind::Variable);
+    EXPECT_EQ(H->NamespaceScope, "");
+    EXPECT_EQ(H->LocalScope, "");
+    EXPECT_EQ(H->Type, "const Foo::Bar");
+    EXPECT_EQ(H->Definition, "constexpr auto vc = Foo::C");
+    // FIXME: Should be "C (0xFFFFFFFFFFFFFFFF)");
+    EXPECT_EQ(H->Value, "18446744073709551615");
+  }
+}
 } // namespace
 } // namespace clangd
 } // namespace clang

>From 68c88bb17e2dc879f6f7f8786a787bc0ce6949cc Mon Sep 17 00:00:00 2001
From: Mythreya <[email protected]>
Date: Sun, 21 Dec 2025 05:30:12 -0800
Subject: [PATCH 2/3] update test

---
 .../clangd/unittests/HoverTests.cpp           | 86 ++++++++++---------
 1 file changed, 46 insertions(+), 40 deletions(-)

diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp 
b/clang-tools-extra/clangd/unittests/HoverTests.cpp
index 0c8423bd5fb2a..725651a92d4fd 100644
--- a/clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -5018,10 +5018,10 @@ TEST(Hover, FunctionParameters) {
 TEST(Hover, GH2381) {
   Annotations Code(R"cpp(
   struct Foo {
-    enum Bar {
-      A = -42UL,
-      B = ~0UL,
-      C = 0xFFFFFFFFFFFFFFFFUL,
+    enum Bar : unsigned long long int {
+      A = -42ULL,
+      B = ~0ULL,
+      C = 0xFFFFFFFFFFFFFFFFULL,
     };
   };
   constexpr auto va$a^ = Foo::A;
@@ -5030,48 +5030,54 @@ TEST(Hover, GH2381) {
   )cpp");
 
   TestTU TU = TestTU::withCode(Code.code());
-  auto AST = TU.build();
 
-  {
-    auto H = getHover(AST, Code.point("a"), format::getLLVMStyle(), nullptr);
+  for (const auto *Triplet :
+       {"--target=x86_64-pc-windows-msvc", "--target=x86_64-pc-linux-gnu"}) {
+    SCOPED_TRACE(Triplet);
+    TU.ExtraArgs.push_back(Triplet);
+    auto AST = TU.build();
 
-    ASSERT_TRUE(H);
-    EXPECT_EQ(H->Name, "va");
-    EXPECT_EQ(H->Kind, index::SymbolKind::Variable);
-    EXPECT_EQ(H->NamespaceScope, "");
-    EXPECT_EQ(H->LocalScope, "");
-    EXPECT_EQ(H->Type, "const Foo::Bar");
-    EXPECT_EQ(H->Definition, "constexpr auto va = Foo::A");
-    // FIXME: Should be "A (FFFFFFFFFFFFFFD6)
-    EXPECT_EQ(H->Value, "18446744073709551574");
-  }
+    {
+      auto H = getHover(AST, Code.point("a"), format::getLLVMStyle(), nullptr);
 
-  {
-    auto H = getHover(AST, Code.point("b"), format::getLLVMStyle(), nullptr);
+      ASSERT_TRUE(H);
+      EXPECT_EQ(H->Name, "va");
+      EXPECT_EQ(H->Kind, index::SymbolKind::Variable);
+      EXPECT_EQ(H->NamespaceScope, "");
+      EXPECT_EQ(H->LocalScope, "");
+      EXPECT_EQ(H->Type, "const Foo::Bar");
+      EXPECT_EQ(H->Definition, "constexpr auto va = Foo::A");
+      // FIXME: Should be "A (FFFFFFFFFFFFFFD6)
+      EXPECT_EQ(H->Value, "18446744073709551574");
+    }
 
-    ASSERT_TRUE(H);
-    EXPECT_EQ(H->Name, "vb");
-    EXPECT_EQ(H->Kind, index::SymbolKind::Variable);
-    EXPECT_EQ(H->NamespaceScope, "");
-    EXPECT_EQ(H->LocalScope, "");
-    EXPECT_EQ(H->Type, "const Foo::Bar");
-    EXPECT_EQ(H->Definition, "constexpr auto vb = Foo::B");
-    // FIXME: Should be "B (0xFFFFFFFFFFFFFFFF)");
-    EXPECT_EQ(H->Value, "18446744073709551615");
-  }
+    {
+      auto H = getHover(AST, Code.point("b"), format::getLLVMStyle(), nullptr);
 
-  {
-    auto H = getHover(AST, Code.point("c"), format::getLLVMStyle(), nullptr);
+      ASSERT_TRUE(H);
+      EXPECT_EQ(H->Name, "vb");
+      EXPECT_EQ(H->Kind, index::SymbolKind::Variable);
+      EXPECT_EQ(H->NamespaceScope, "");
+      EXPECT_EQ(H->LocalScope, "");
+      EXPECT_EQ(H->Type, "const Foo::Bar");
+      EXPECT_EQ(H->Definition, "constexpr auto vb = Foo::B");
+      // FIXME: Should be "B (0xFFFFFFFFFFFFFFFF)");
+      EXPECT_EQ(H->Value, "18446744073709551615");
+    }
 
-    ASSERT_TRUE(H);
-    EXPECT_EQ(H->Name, "vc");
-    EXPECT_EQ(H->Kind, index::SymbolKind::Variable);
-    EXPECT_EQ(H->NamespaceScope, "");
-    EXPECT_EQ(H->LocalScope, "");
-    EXPECT_EQ(H->Type, "const Foo::Bar");
-    EXPECT_EQ(H->Definition, "constexpr auto vc = Foo::C");
-    // FIXME: Should be "C (0xFFFFFFFFFFFFFFFF)");
-    EXPECT_EQ(H->Value, "18446744073709551615");
+    {
+      auto H = getHover(AST, Code.point("c"), format::getLLVMStyle(), nullptr);
+
+      ASSERT_TRUE(H);
+      EXPECT_EQ(H->Name, "vc");
+      EXPECT_EQ(H->Kind, index::SymbolKind::Variable);
+      EXPECT_EQ(H->NamespaceScope, "");
+      EXPECT_EQ(H->LocalScope, "");
+      EXPECT_EQ(H->Type, "const Foo::Bar");
+      EXPECT_EQ(H->Definition, "constexpr auto vc = Foo::C");
+      // FIXME: Should be "C (0xFFFFFFFFFFFFFFFF)");
+      EXPECT_EQ(H->Value, "18446744073709551615");
+    }
   }
 }
 } // namespace

>From b10e34df955c6e52ac4be4c7399fc4b2759843a8 Mon Sep 17 00:00:00 2001
From: Mythreya <[email protected]>
Date: Sun, 21 Dec 2025 06:08:53 -0800
Subject: [PATCH 3/3] Update handling for ULL enums

---
 clang-tools-extra/clangd/Hover.cpp            | 28 +++++++++++++------
 .../clangd/unittests/HoverTests.cpp           | 22 ++-------------
 2 files changed, 21 insertions(+), 29 deletions(-)

diff --git a/clang-tools-extra/clangd/Hover.cpp 
b/clang-tools-extra/clangd/Hover.cpp
index 7ec7e6d19105a..24fcbd27b2516 100644
--- a/clang-tools-extra/clangd/Hover.cpp
+++ b/clang-tools-extra/clangd/Hover.cpp
@@ -57,6 +57,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/ScopedPrinter.h"
 #include "llvm/Support/raw_ostream.h"
@@ -450,15 +451,24 @@ std::optional<std::string> printExprValue(const Expr *E,
     return std::nullopt;
 
   // Show enums symbolically, not numerically like APValue::printPretty().
-  if (T->isEnumeralType() && Constant.Val.isInt() &&
-      Constant.Val.getInt().isRepresentableByInt64()) {
-    // Compare to int64_t to avoid bit-width match requirements.
-    int64_t Val = Constant.Val.getInt().getExtValue();
-    for (const EnumConstantDecl *ECD : T->castAsEnumDecl()->enumerators())
-      if (ECD->getInitVal() == Val)
-        return llvm::formatv("{0} ({1})", ECD->getNameAsString(),
-                             printHex(Constant.Val.getInt()))
-            .str();
+  if (T->isEnumeralType() && Constant.Val.isInt()) {
+    const llvm::APSInt Val = Constant.Val.getInt();
+    if (Val.isRepresentableByInt64()) {
+      // Compare to int64_t to avoid bit-width match requirements.
+      int64_t Val = Constant.Val.getInt().getExtValue();
+      for (const EnumConstantDecl *ECD : T->castAsEnumDecl()->enumerators())
+        if (ECD->getInitVal() == Val)
+          return llvm::formatv("{0} ({1})", ECD->getNameAsString(),
+                               printHex(Constant.Val.getInt()))
+              .str();
+    } else if (auto UVal = Constant.Val.getInt().tryZExtValue()) {
+      for (const EnumConstantDecl *ECD : T->castAsEnumDecl()->enumerators())
+        if (ECD->getInitVal().getZExtValue() == *UVal)
+          return llvm::formatv("{0} ({1})", ECD->getNameAsString(),
+                               printHex(Constant.Val.getInt()))
+              .str();
+    } else
+      llvm_unreachable("Unhandled branch in enum symbolic representation");
   }
   // Show hex value of integers if they're at least 10 (or negative!)
   if (T->isIntegralOrEnumerationType() && Constant.Val.isInt() &&
diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp 
b/clang-tools-extra/clangd/unittests/HoverTests.cpp
index 725651a92d4fd..1b0edc2bcfeb5 100644
--- a/clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -5021,12 +5021,10 @@ TEST(Hover, GH2381) {
     enum Bar : unsigned long long int {
       A = -42ULL,
       B = ~0ULL,
-      C = 0xFFFFFFFFFFFFFFFFULL,
     };
   };
   constexpr auto va$a^ = Foo::A;
   constexpr auto vb$b^ = Foo::B;
-  constexpr auto vc$c^ = Foo::C;
   )cpp");
 
   TestTU TU = TestTU::withCode(Code.code());
@@ -5047,8 +5045,7 @@ TEST(Hover, GH2381) {
       EXPECT_EQ(H->LocalScope, "");
       EXPECT_EQ(H->Type, "const Foo::Bar");
       EXPECT_EQ(H->Definition, "constexpr auto va = Foo::A");
-      // FIXME: Should be "A (FFFFFFFFFFFFFFD6)
-      EXPECT_EQ(H->Value, "18446744073709551574");
+      EXPECT_EQ(H->Value, "A (0xffffffffffffffd6)");
     }
 
     {
@@ -5061,22 +5058,7 @@ TEST(Hover, GH2381) {
       EXPECT_EQ(H->LocalScope, "");
       EXPECT_EQ(H->Type, "const Foo::Bar");
       EXPECT_EQ(H->Definition, "constexpr auto vb = Foo::B");
-      // FIXME: Should be "B (0xFFFFFFFFFFFFFFFF)");
-      EXPECT_EQ(H->Value, "18446744073709551615");
-    }
-
-    {
-      auto H = getHover(AST, Code.point("c"), format::getLLVMStyle(), nullptr);
-
-      ASSERT_TRUE(H);
-      EXPECT_EQ(H->Name, "vc");
-      EXPECT_EQ(H->Kind, index::SymbolKind::Variable);
-      EXPECT_EQ(H->NamespaceScope, "");
-      EXPECT_EQ(H->LocalScope, "");
-      EXPECT_EQ(H->Type, "const Foo::Bar");
-      EXPECT_EQ(H->Definition, "constexpr auto vc = Foo::C");
-      // FIXME: Should be "C (0xFFFFFFFFFFFFFFFF)");
-      EXPECT_EQ(H->Value, "18446744073709551615");
+      EXPECT_EQ(H->Value, "B (0xffffffffffffffff)");
     }
   }
 }

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to