summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKadir Cetinkaya <kadircet@google.com>2020-01-30 18:42:01 +0100
committerSam McCall <sam.mccall@gmail.com>2020-06-10 11:53:19 +0200
commit30d05b898c6e84160507a66aabba6aceb129a9c7 (patch)
tree5f59520e7718aa1951b2429c2492d4eebff08c82
parent3f4a753f597357db77fe395561234a50daa451b3 (diff)
downloadbcm5719-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.cpp18
-rw-r--r--clang-tools-extra/clangd/unittests/HoverTests.cpp16
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.
OpenPOWER on IntegriCloud