llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-tools-extra

Author: Mythreya Kuricheti (MythreyaK)

<details>
<summary>Changes</summary>

Fix clangd crash when hovering over 64bit values with MSB set. 

Fixes clangd/clangd#<!-- -->2381

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


2 Files Affected:

- (modified) clang-tools-extra/clangd/Hover.cpp (+20-10) 
- (modified) clang-tools-extra/clangd/unittests/HoverTests.cpp (+47) 


``````````diff
diff --git a/clang-tools-extra/clangd/Hover.cpp 
b/clang-tools-extra/clangd/Hover.cpp
index 34369e188d4ec..0d6db829b49f7 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,19 +451,28 @@ 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().getSignificantBits() <= 64) {
-    // 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 (const 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() &&
-      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..1b0edc2bcfeb5 100644
--- a/clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -5015,6 +5015,53 @@ TEST(Hover, FunctionParameters) {
   }
 }
 
+TEST(Hover, GH2381) {
+  Annotations Code(R"cpp(
+  struct Foo {
+    enum Bar : unsigned long long int {
+      A = -42ULL,
+      B = ~0ULL,
+    };
+  };
+  constexpr auto va$a^ = Foo::A;
+  constexpr auto vb$b^ = Foo::B;
+  )cpp");
+
+  TestTU TU = TestTU::withCode(Code.code());
+
+  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();
+
+    {
+      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");
+      EXPECT_EQ(H->Value, "A (0xffffffffffffffd6)");
+    }
+
+    {
+      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");
+      EXPECT_EQ(H->Value, "B (0xffffffffffffffff)");
+    }
+  }
+}
 } // namespace
 } // namespace clangd
 } // namespace clang

``````````

</details>


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

Reply via email to