diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp --- a/clang-tools-extra/clangd/Hover.cpp +++ b/clang-tools-extra/clangd/Hover.cpp @@ -952,6 +952,15 @@ } } +HoverInfo::PassType::PassMode getPassMode(QualType ParmType) { + if (ParmType->isReferenceType()) { + if (ParmType->getPointeeType().isConstQualified()) + return HoverInfo::PassType::ConstRef; + return HoverInfo::PassType::Ref; + } + return HoverInfo::PassType::Value; +} + // If N is passed as argument to a function, fill HI.CalleeArgInfo with // information about that argument. void maybeAddCalleeArgInfo(const SelectionTree::Node *N, HoverInfo &HI, @@ -972,14 +981,19 @@ if (!FD || FD->isOverloadedOperator() || FD->isVariadic()) return; + HoverInfo::PassType PassType; + // Find argument index for N. for (unsigned I = 0; I < CE->getNumArgs() && I < FD->getNumParams(); ++I) { if (CE->getArg(I) != OuterNode.ASTNode.get()) continue; // Extract matching argument from function declaration. - if (const ParmVarDecl *PVD = FD->getParamDecl(I)) + if (const ParmVarDecl *PVD = FD->getParamDecl(I)) { HI.CalleeArgInfo.emplace(toHoverInfoParam(PVD, PP)); + if (N == &OuterNode) + PassType.PassBy = getPassMode(PVD->getType()); + } break; } if (!HI.CalleeArgInfo) @@ -988,14 +1002,9 @@ // If we found a matching argument, also figure out if it's a // [const-]reference. For this we need to walk up the AST from the arg itself // to CallExpr and check all implicit casts, constructor calls, etc. - HoverInfo::PassType PassType; if (const auto *E = N->ASTNode.get()) { if (E->getType().isConstQualified()) PassType.PassBy = HoverInfo::PassType::ConstRef; - - // No implicit node, literal passed by value - if (isLiteral(E) && N->Parent == OuterNode.Parent) - PassType.PassBy = HoverInfo::PassType::Value; } for (auto *CastNode = N->Parent; @@ -1067,9 +1076,8 @@ // template void bar() { fo^o(T{}); } // we actually want to show the using declaration, // it's not clear which declaration to pick otherwise. - auto BaseDecls = llvm::make_filter_range(Candidates, [](const NamedDecl *D) { - return llvm::isa(D); - }); + auto BaseDecls = llvm::make_filter_range( + Candidates, [](const NamedDecl *D) { return llvm::isa(D); }); if (std::distance(BaseDecls.begin(), BaseDecls.end()) == 1) return *BaseDecls.begin(); diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp --- a/clang-tools-extra/clangd/unittests/HoverTests.cpp +++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -900,6 +900,27 @@ HI.CalleeArgInfo->Type = "int &"; HI.CallPassType = HoverInfo::PassType{PassMode::Ref, false}; }}, + { + R"cpp( + void foobar(const float &arg); + int main() { + int a = 0; + foobar([[^a]]); + } + )cpp", + [](HoverInfo &HI) { + HI.Name = "a"; + HI.Kind = index::SymbolKind::Variable; + HI.NamespaceScope = ""; + HI.Definition = "int a = 0"; + HI.LocalScope = "main::"; + HI.Value = "0"; + HI.Type = "int"; + HI.CalleeArgInfo.emplace(); + HI.CalleeArgInfo->Name = "arg"; + HI.CalleeArgInfo->Type = "const float &"; + HI.CallPassType = HoverInfo::PassType{PassMode::Value, true}; + }}, {// Literal passed to function call R"cpp( void fun(int arg_a, const int &arg_b) {}; @@ -934,6 +955,38 @@ HI.CalleeArgInfo->Type = "const int &"; HI.CallPassType = HoverInfo::PassType{PassMode::ConstRef, false}; }}, + { + R"cpp( + int add(int lhs, int rhs); + int main() { + add(1 [[^+]] 2, 3); + } + )cpp", + [](HoverInfo &HI) { + HI.Name = "expression"; + HI.Kind = index::SymbolKind::Unknown; + HI.Type = "int"; + HI.Value = "3"; + HI.CalleeArgInfo.emplace(); + HI.CalleeArgInfo->Name = "lhs"; + HI.CalleeArgInfo->Type = "int"; + HI.CallPassType = HoverInfo::PassType{PassMode::Value, false}; + }}, + { + R"cpp( + void foobar(const float &arg); + int main() { + foobar([[^0]]); + } + )cpp", + [](HoverInfo &HI) { + HI.Name = "literal"; + HI.Kind = index::SymbolKind::Unknown; + HI.CalleeArgInfo.emplace(); + HI.CalleeArgInfo->Name = "arg"; + HI.CalleeArgInfo->Type = "const float &"; + HI.CallPassType = HoverInfo::PassType{PassMode::Value, true}; + }}, {// Extra info for method call. R"cpp( class C { @@ -960,6 +1013,29 @@ HI.CalleeArgInfo->Default = "3"; HI.CallPassType = HoverInfo::PassType{PassMode::Value, false}; }}, + { + R"cpp( + struct Foo { + Foo(const int &); + }; + void foo(Foo); + void bar() { + const int x = 0; + foo([[^x]]); + } + )cpp", + [](HoverInfo &HI) { + HI.Name = "x"; + HI.Kind = index::SymbolKind::Variable; + HI.NamespaceScope = ""; + HI.Definition = "const int x = 0"; + HI.LocalScope = "bar::"; + HI.Value = "0"; + HI.Type = "const int"; + HI.CalleeArgInfo.emplace(); + HI.CalleeArgInfo->Type = "Foo"; + HI.CallPassType = HoverInfo::PassType{PassMode::ConstRef, true}; + }}, {// Dont crash on invalid decl R"cpp( // error-ok @@ -1673,8 +1749,8 @@ }}, { R"cpp(// Function definition via using declaration - namespace ns { - void foo(); + namespace ns { + void foo(); } int main() { using ns::foo;