forked from OSchip/llvm-project
[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.
This commit is contained in:
parent
8af74da5bd
commit
72142fbac4
|
@ -430,7 +430,8 @@ llvm::Optional<std::string> 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 :
|
||||
|
@ -441,7 +442,7 @@ llvm::Optional<std::string> 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),
|
||||
|
|
|
@ -3234,6 +3234,41 @@ TEST(Hover, HideBigInitializers) {
|
|||
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<Test>(reinterpret_cast<uintptr_t>(&global_var));
|
||||
}
|
||||
)cpp");
|
||||
|
||||
TestTU TU = TestTU::withCode(T.code());
|
||||
TU.PredefineMacros = true;
|
||||
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<uintptr_t>(&global_var);
|
||||
}
|
||||
)cpp");
|
||||
|
||||
TestTU TU = TestTU::withCode(T.code());
|
||||
TU.PredefineMacros = true;
|
||||
auto AST = TU.build();
|
||||
auto HI = getHover(AST, T.point(), format::getLLVMStyle(), nullptr);
|
||||
ASSERT_TRUE(HI);
|
||||
EXPECT_EQ(*HI->Value, "&global_var");
|
||||
}
|
||||
|
||||
TEST(Hover, Typedefs) {
|
||||
Annotations T(R"cpp(
|
||||
template <bool X, typename T, typename F>
|
||||
|
|
|
@ -40,9 +40,12 @@ ParseInputs TestTU::inputs(MockFS &FS) const {
|
|||
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 (!PredefineMacros)
|
||||
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()) {
|
||||
|
|
|
@ -59,6 +59,9 @@ struct TestTU {
|
|||
// Extra arguments for the compiler invocation.
|
||||
std::vector<std::string> ExtraArgs;
|
||||
|
||||
// Predefine macros such as __UINTPTR_TYPE__.
|
||||
bool PredefineMacros = false;
|
||||
|
||||
TidyProvider ClangTidyProvider = {};
|
||||
// Index to use when building AST.
|
||||
const SymbolIndex *ExternalIndex = nullptr;
|
||||
|
|
Loading…
Reference in New Issue