diff options
author | Kadir Cetinkaya <kadircet@google.com> | 2020-01-30 18:42:01 +0100 |
---|---|---|
committer | Sam McCall <sam.mccall@gmail.com> | 2020-06-10 11:53:19 +0200 |
commit | 30d05b898c6e84160507a66aabba6aceb129a9c7 (patch) | |
tree | 5f59520e7718aa1951b2429c2492d4eebff08c82 | |
parent | 3f4a753f597357db77fe395561234a50daa451b3 (diff) | |
download | bcm5719-llvm-30d05b898c6e84160507a66aabba6aceb129a9c7.tar.gz bcm5719-llvm-30d05b898c6e84160507a66aabba6aceb129a9c7.zip |
[clangd][Hover] Handle uninstantiated default args
Summary:
Default args might exist but be unparsed or uninstantiated.
getDefaultArg asserts on those. This patch makes sure we don't crash in such
scenarios.
Reviewers: sammccall, ilya-biryukov
Subscribers: MaskRay, jkorous, arphaman, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D73723
(cherry-picked from commit 9c903d0373ff940f9143efab8d948edf776de9f1)
Fixes https://github.com/clangd/clangd/issues/424
-rw-r--r-- | clang-tools-extra/clangd/Hover.cpp | 18 | ||||
-rw-r--r-- | clang-tools-extra/clangd/unittests/HoverTests.cpp | 16 |
2 files changed, 32 insertions, 2 deletions
diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp index 834c9d04187..e41b4b8e5e1 100644 --- a/clang-tools-extra/clangd/Hover.cpp +++ b/clang-tools-extra/clangd/Hover.cpp @@ -249,6 +249,20 @@ void enhanceFromIndex(HoverInfo &Hover, const NamedDecl &ND, Req, [&](const Symbol &S) { Hover.Documentation = S.Documentation; }); } +// Default argument might exist but be unavailable, in the case of unparsed +// arguments for example. This function returns the default argument if it is +// available. +const Expr *getDefaultArg(const ParmVarDecl *PVD) { + // Default argument can be unparsed or uninstatiated. For the former we + // can't do much, as token information is only stored in Sema and not + // attached to the AST node. For the latter though, it is safe to proceed as + // the expression is still valid. + if (!PVD->hasDefaultArg() || PVD->hasUnparsedDefaultArg()) + return nullptr; + return PVD->hasUninstantiatedDefaultArg() ? PVD->getUninstantiatedDefaultArg() + : PVD->getDefaultArg(); +} + // Populates Type, ReturnType, and Parameters for function-like decls. void fillFunctionTypeAndParams(HoverInfo &HI, const Decl *D, const FunctionDecl *FD, @@ -268,10 +282,10 @@ void fillFunctionTypeAndParams(HoverInfo &HI, const Decl *D, } if (!PVD->getName().empty()) P.Name = PVD->getNameAsString(); - if (PVD->hasDefaultArg()) { + if (const Expr *DefArg = getDefaultArg(PVD)) { P.Default.emplace(); llvm::raw_string_ostream Out(*P.Default); - PVD->getDefaultArg()->printPretty(Out, nullptr, Policy); + DefArg->printPretty(Out, nullptr, Policy); } } diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp index bdac5be0ac3..89b529d9b41 100644 --- a/clang-tools-extra/clangd/unittests/HoverTests.cpp +++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -1615,6 +1615,22 @@ TEST(Hover, All) { HI.Type = "unsigned long"; HI.Value = "1"; }}, + { + R"cpp( + template <typename T = int> + void foo(const T& = T()) { + [[f^oo]]<>(3); + })cpp", + [](HoverInfo &HI) { + HI.Name = "foo"; + HI.Kind = index::SymbolKind::Function; + HI.Type = "void (const int &)"; + HI.ReturnType = "void"; + HI.Parameters = { + {std::string("const int &"), llvm::None, std::string("T()")}}; + HI.Definition = "template <> void foo<int>(const int &)"; + HI.NamespaceScope = ""; + }}, }; // Create a tiny index, so tests above can verify documentation is fetched. |