- Notifications
You must be signed in to change notification settings - Fork 15.6k
[clangd] Fix crash on hover over 64bit enums with MSB set #173187
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
base: main
Are you sure you want to change the base?
Conversation
6ab4a4f to e23269b Compare 🪟 Windows x64 Test Results
✅ The build succeeded and all tests passed. |
UL enums with MSB setb10e34d to 046689a Compare | } 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(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not confident if this is the right thing to do, still exploring this API.
| @llvm/pr-subscribers-clang-tools-extra Author: Mythreya Kuricheti (MythreyaK) ChangesFix 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:
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 |
| @llvm/pr-subscribers-clangd Author: Mythreya Kuricheti (MythreyaK) ChangesFix 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:
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 |
Fix clangd crash when hovering over 64bit values with MSB set.
Fixes clangd/clangd#2381