From ce5ebf0b9113df8ccaec1bcfd6804fb16cdef69d Mon Sep 17 00:00:00 2001 From: Georg Kotheimer Date: Tue, 31 May 2022 21:57:51 +0200 Subject: [PATCH] [clangd] Fix hover crashing on integral or enumeral casts When pretty printing the value of an expression, we cannot infer from the type of the expression the type of the constant that the expression evaluates to, as the expression might contain a type cast. --- clang-tools-extra/clangd/Hover.cpp | 5 +++-- clang-tools-extra/clangd/unittests/HoverTests.cpp | 27 +++++++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp index fcf3af7..00fb992 100644 --- a/clang-tools-extra/clangd/Hover.cpp +++ b/clang-tools-extra/clangd/Hover.cpp @@ -429,7 +429,8 @@ llvm::Optional printExprValue(const Expr *E, return llvm::None; // Show enums symbolically, not numerically like APValue::printPretty(). - if (T->isEnumeralType() && Constant.Val.getInt().getMinSignedBits() <= 64) { + if (T->isEnumeralType() && Constant.Val.isInt() && + Constant.Val.getInt().getMinSignedBits() <= 64) { // Compare to int64_t to avoid bit-width match requirements. int64_t Val = Constant.Val.getInt().getExtValue(); for (const EnumConstantDecl *ECD : @@ -440,7 +441,7 @@ llvm::Optional printExprValue(const Expr *E, .str(); } // Show hex value of integers if they're at least 10 (or negative!) - if (T->isIntegralOrEnumerationType() && + if (T->isIntegralOrEnumerationType() && Constant.Val.isInt() && Constant.Val.getInt().getMinSignedBits() <= 64 && Constant.Val.getInt().uge(10)) return llvm::formatv("{0} ({1})", Constant.Val.getAsString(Ctx, T), diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp index 25ce19b..86ecda4 100644 --- a/clang-tools-extra/clangd/unittests/HoverTests.cpp +++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -3206,6 +3206,33 @@ TEST(Hover, HideBigInitializers) { ASSERT_TRUE(H); EXPECT_EQ(H->Definition, "int arr[]"); } + +TEST(Hover, GlobalVarEnumeralCastNoCrash) { + Annotations T(R"cpp( + enum Test : unsigned long {}; + unsigned global_var; + void foo() { Test v^al = (Test)(unsigned long)&global_var; } + )cpp"); + + TestTU TU = TestTU::withCode(T.code()); + auto AST = TU.build(); + auto HI = getHover(AST, T.point(), format::getLLVMStyle(), nullptr); + ASSERT_TRUE(HI); + EXPECT_EQ(*HI->Value, "&global_var"); +} + +TEST(Hover, GlobalVarIntCastNoCrash) { + Annotations T(R"cpp( + unsigned global_var; + int foo() { unsigned long a^ddress = (unsigned long)&global_var; } + )cpp"); + + TestTU TU = TestTU::withCode(T.code()); + auto AST = TU.build(); + auto HI = getHover(AST, T.point(), format::getLLVMStyle(), nullptr); + ASSERT_TRUE(HI); + EXPECT_EQ(*HI->Value, "&global_var"); +} } // namespace } // namespace clangd } // namespace clang -- 2.7.4