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
