Index: clang-tools-extra/clangd/Hover.cpp =================================================================== --- clang-tools-extra/clangd/Hover.cpp +++ clang-tools-extra/clangd/Hover.cpp @@ -429,7 +429,8 @@ 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 @@ .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), Index: clang-tools-extra/clangd/unittests/HoverTests.cpp =================================================================== --- clang-tools-extra/clangd/unittests/HoverTests.cpp +++ clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -3206,6 +3206,41 @@ ASSERT_TRUE(H); EXPECT_EQ(H->Definition, "int arr[]"); } + +TEST(Hover, GlobalVarEnumeralCastNoCrash) { + Annotations T(R"cpp( + using uintptr_t = __UINTPTR_TYPE__; + enum Test : uintptr_t {}; + unsigned global_var; + void foo() { + Test v^al = static_cast(reinterpret_cast(&global_var)); + } + )cpp"); + + TestTU TU = TestTU::withCode(T.code()); + TU.OmitPredefinedMacros = false; + 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( + using uintptr_t = __UINTPTR_TYPE__; + unsigned global_var; + void foo() { + uintptr_t a^ddress = reinterpret_cast(&global_var); + } + )cpp"); + + TestTU TU = TestTU::withCode(T.code()); + TU.OmitPredefinedMacros = false; + 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 Index: clang-tools-extra/clangd/unittests/TestTU.h =================================================================== --- clang-tools-extra/clangd/unittests/TestTU.h +++ clang-tools-extra/clangd/unittests/TestTU.h @@ -59,6 +59,9 @@ // Extra arguments for the compiler invocation. std::vector ExtraArgs; + // Omit predefined macros. + bool OmitPredefinedMacros = true; + TidyProvider ClangTidyProvider = {}; // Index to use when building AST. const SymbolIndex *ExternalIndex = nullptr; Index: clang-tools-extra/clangd/unittests/TestTU.cpp =================================================================== --- clang-tools-extra/clangd/unittests/TestTU.cpp +++ clang-tools-extra/clangd/unittests/TestTU.cpp @@ -40,9 +40,12 @@ ParseInputs Inputs; Inputs.FeatureModules = FeatureModules; auto &Argv = Inputs.CompileCommand.CommandLine; - // In tests, omit predefined macros (__GNUC__ etc) for a 25% speedup. - // There are hundreds, and we'd generate, parse, serialize, and re-parse them! - Argv = {"clang", "-Xclang", "-undef"}; + Argv = {"clang", "-Xclang"}; + // In tests, unless explicitly specified otherwise, omit predefined macros + // (__GNUC__ etc) for a 25% speedup. There are hundreds, and we'd generate, + // parse, serialize, and re-parse them! + if (OmitPredefinedMacros) + Argv.push_back("-undef"); // FIXME: this shouldn't need to be conditional, but it breaks a // GoToDefinition test for some reason (getMacroArgExpandedLocation fails). if (!HeaderCode.empty()) {