diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp index 3d5d002f8ded8..bd5b7114cc357 100644 --- a/clang-tools-extra/clangd/Hover.cpp +++ b/clang-tools-extra/clangd/Hover.cpp @@ -124,8 +124,8 @@ std::string printType(QualType QT, const PrintingPolicy &Policy) { // TypePrinter doesn't resolve decltypes, so resolve them here. // FIXME: This doesn't handle composite types that contain a decltype in them. // We should rather have a printing policy for that. - while (const auto *DT = QT->getAs()) - QT = DT->getUnderlyingType(); + while (!QT.isNull() && QT->isDecltypeType()) + QT = QT->getAs()->getUnderlyingType(); return QT.getAsString(Policy); } @@ -297,15 +297,7 @@ void fillFunctionTypeAndParams(HoverInfo &HI, const Decl *D, for (const ParmVarDecl *PVD : FD->parameters()) { HI.Parameters->emplace_back(); auto &P = HI.Parameters->back(); - if (!PVD->getType().isNull()) { - P.Type = printType(PVD->getType(), Policy); - } else { - std::string Param; - llvm::raw_string_ostream OS(Param); - PVD->dump(OS); - OS.flush(); - elog("Got param with null type: {0}", Param); - } + P.Type = printType(PVD->getType(), Policy); if (!PVD->getName().empty()) P.Name = PVD->getNameAsString(); if (const Expr *DefArg = getDefaultArg(PVD)) { diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp index c6c0daa6380e4..78964ee7ab919 100644 --- a/clang-tools-extra/clangd/unittests/HoverTests.cpp +++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -708,6 +708,17 @@ class Foo {})cpp"; HI.Definition = "X x"; HI.Type = "struct X"; }}, + {// Don't crash on null types. + R"cpp(auto [^[[x]]] = 1; /*error-ok*/)cpp", + [](HoverInfo &HI) { + HI.Name = "x"; + HI.Kind = index::SymbolKind::Variable; + HI.NamespaceScope = ""; + HI.Definition = ""; + HI.Type = "NULL TYPE"; + // Bindings are in theory public members of an anonymous struct. + HI.AccessSpecifier = "public"; + }}, }; for (const auto &Case : Cases) { SCOPED_TRACE(Case.Code);