[clang-tools-extra] 72142fb - [clangd] Fix hover crashing on integral or enumeral casts

Sam McCall via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 7 07:54:57 PDT 2022


Author: Georg Kotheimer
Date: 2022-09-07T16:43:22+02:00
New Revision: 72142fbac496a66769e16c80b076216d7c449ab2

URL: https://github.com/llvm/llvm-project/commit/72142fbac496a66769e16c80b076216d7c449ab2
DIFF: https://github.com/llvm/llvm-project/commit/72142fbac496a66769e16c80b076216d7c449ab2.diff

LOG: [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.

Added: 
    

Modified: 
    clang-tools-extra/clangd/Hover.cpp
    clang-tools-extra/clangd/unittests/HoverTests.cpp
    clang-tools-extra/clangd/unittests/TestTU.cpp
    clang-tools-extra/clangd/unittests/TestTU.h

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp
index eb44d1e915af..61c4d0658c91 100644
--- a/clang-tools-extra/clangd/Hover.cpp
+++ b/clang-tools-extra/clangd/Hover.cpp
@@ -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),

diff  --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp
index 997b761e6a69..d9596dc7e693 100644
--- a/clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -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>

diff  --git a/clang-tools-extra/clangd/unittests/TestTU.cpp b/clang-tools-extra/clangd/unittests/TestTU.cpp
index 3da108682960..f7d294ca2c26 100644
--- a/clang-tools-extra/clangd/unittests/TestTU.cpp
+++ b/clang-tools-extra/clangd/unittests/TestTU.cpp
@@ -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()) {

diff  --git a/clang-tools-extra/clangd/unittests/TestTU.h b/clang-tools-extra/clangd/unittests/TestTU.h
index b045efb727c7..9346d19e0407 100644
--- a/clang-tools-extra/clangd/unittests/TestTU.h
+++ b/clang-tools-extra/clangd/unittests/TestTU.h
@@ -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;


        


More information about the cfe-commits mailing list