Skip to content

Commit b252824

Browse files
committed
[clangd] fix wrong CalleeArgInfo in the hover
``` void foobar(int); int main() { foobar(1 + 2); ^ } ``` Currently the CalleeArgInfo will be "Passed by reference", which should be "Passed by value". Fixes clangd/clangd#1467 Differential Revision: https://reviews.llvm.org/D142014
1 parent 08061a5 commit b252824

File tree

2 files changed

+95
-11
lines changed

2 files changed

+95
-11
lines changed

clang-tools-extra/clangd/Hover.cpp

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -952,6 +952,15 @@ void addLayoutInfo(const NamedDecl &ND, HoverInfo &HI) {
952952
}
953953
}
954954

955+
HoverInfo::PassType::PassMode getPassMode(QualType ParmType) {
956+
if (ParmType->isReferenceType()) {
957+
if (ParmType->getPointeeType().isConstQualified())
958+
return HoverInfo::PassType::ConstRef;
959+
return HoverInfo::PassType::Ref;
960+
}
961+
return HoverInfo::PassType::Value;
962+
}
963+
955964
// If N is passed as argument to a function, fill HI.CalleeArgInfo with
956965
// information about that argument.
957966
void maybeAddCalleeArgInfo(const SelectionTree::Node *N, HoverInfo &HI,
@@ -972,14 +981,19 @@ void maybeAddCalleeArgInfo(const SelectionTree::Node *N, HoverInfo &HI,
972981
if (!FD || FD->isOverloadedOperator() || FD->isVariadic())
973982
return;
974983

984+
HoverInfo::PassType PassType;
985+
975986
// Find argument index for N.
976987
for (unsigned I = 0; I < CE->getNumArgs() && I < FD->getNumParams(); ++I) {
977988
if (CE->getArg(I) != OuterNode.ASTNode.get<Expr>())
978989
continue;
979990

980991
// Extract matching argument from function declaration.
981-
if (const ParmVarDecl *PVD = FD->getParamDecl(I))
992+
if (const ParmVarDecl *PVD = FD->getParamDecl(I)) {
982993
HI.CalleeArgInfo.emplace(toHoverInfoParam(PVD, PP));
994+
if (N == &OuterNode)
995+
PassType.PassBy = getPassMode(PVD->getType());
996+
}
983997
break;
984998
}
985999
if (!HI.CalleeArgInfo)
@@ -988,14 +1002,9 @@ void maybeAddCalleeArgInfo(const SelectionTree::Node *N, HoverInfo &HI,
9881002
// If we found a matching argument, also figure out if it's a
9891003
// [const-]reference. For this we need to walk up the AST from the arg itself
9901004
// to CallExpr and check all implicit casts, constructor calls, etc.
991-
HoverInfo::PassType PassType;
9921005
if (const auto *E = N->ASTNode.get<Expr>()) {
9931006
if (E->getType().isConstQualified())
9941007
PassType.PassBy = HoverInfo::PassType::ConstRef;
995-
996-
// No implicit node, literal passed by value
997-
if (isLiteral(E) && N->Parent == OuterNode.Parent)
998-
PassType.PassBy = HoverInfo::PassType::Value;
9991008
}
10001009

10011010
for (auto *CastNode = N->Parent;
@@ -1067,9 +1076,8 @@ const NamedDecl *pickDeclToUse(llvm::ArrayRef<const NamedDecl *> Candidates) {
10671076
// template <typename T> void bar() { fo^o(T{}); }
10681077
// we actually want to show the using declaration,
10691078
// it's not clear which declaration to pick otherwise.
1070-
auto BaseDecls = llvm::make_filter_range(Candidates, [](const NamedDecl *D) {
1071-
return llvm::isa<UsingDecl>(D);
1072-
});
1079+
auto BaseDecls = llvm::make_filter_range(
1080+
Candidates, [](const NamedDecl *D) { return llvm::isa<UsingDecl>(D); });
10731081
if (std::distance(BaseDecls.begin(), BaseDecls.end()) == 1)
10741082
return *BaseDecls.begin();
10751083

clang-tools-extra/clangd/unittests/HoverTests.cpp

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -900,6 +900,27 @@ class Foo final {})cpp";
900900
HI.CalleeArgInfo->Type = "int &";
901901
HI.CallPassType = HoverInfo::PassType{PassMode::Ref, false};
902902
}},
903+
{
904+
R"cpp(
905+
void foobar(const float &arg);
906+
int main() {
907+
int a = 0;
908+
foobar([[^a]]);
909+
}
910+
)cpp",
911+
[](HoverInfo &HI) {
912+
HI.Name = "a";
913+
HI.Kind = index::SymbolKind::Variable;
914+
HI.NamespaceScope = "";
915+
HI.Definition = "int a = 0";
916+
HI.LocalScope = "main::";
917+
HI.Value = "0";
918+
HI.Type = "int";
919+
HI.CalleeArgInfo.emplace();
920+
HI.CalleeArgInfo->Name = "arg";
921+
HI.CalleeArgInfo->Type = "const float &";
922+
HI.CallPassType = HoverInfo::PassType{PassMode::Value, true};
923+
}},
903924
{// Literal passed to function call
904925
R"cpp(
905926
void fun(int arg_a, const int &arg_b) {};
@@ -934,6 +955,38 @@ class Foo final {})cpp";
934955
HI.CalleeArgInfo->Type = "const int &";
935956
HI.CallPassType = HoverInfo::PassType{PassMode::ConstRef, false};
936957
}},
958+
{
959+
R"cpp(
960+
int add(int lhs, int rhs);
961+
int main() {
962+
add(1 [[^+]] 2, 3);
963+
}
964+
)cpp",
965+
[](HoverInfo &HI) {
966+
HI.Name = "expression";
967+
HI.Kind = index::SymbolKind::Unknown;
968+
HI.Type = "int";
969+
HI.Value = "3";
970+
HI.CalleeArgInfo.emplace();
971+
HI.CalleeArgInfo->Name = "lhs";
972+
HI.CalleeArgInfo->Type = "int";
973+
HI.CallPassType = HoverInfo::PassType{PassMode::Value, false};
974+
}},
975+
{
976+
R"cpp(
977+
void foobar(const float &arg);
978+
int main() {
979+
foobar([[^0]]);
980+
}
981+
)cpp",
982+
[](HoverInfo &HI) {
983+
HI.Name = "literal";
984+
HI.Kind = index::SymbolKind::Unknown;
985+
HI.CalleeArgInfo.emplace();
986+
HI.CalleeArgInfo->Name = "arg";
987+
HI.CalleeArgInfo->Type = "const float &";
988+
HI.CallPassType = HoverInfo::PassType{PassMode::Value, true};
989+
}},
937990
{// Extra info for method call.
938991
R"cpp(
939992
class C {
@@ -960,6 +1013,29 @@ class Foo final {})cpp";
9601013
HI.CalleeArgInfo->Default = "3";
9611014
HI.CallPassType = HoverInfo::PassType{PassMode::Value, false};
9621015
}},
1016+
{
1017+
R"cpp(
1018+
struct Foo {
1019+
Foo(const int &);
1020+
};
1021+
void foo(Foo);
1022+
void bar() {
1023+
const int x = 0;
1024+
foo([[^x]]);
1025+
}
1026+
)cpp",
1027+
[](HoverInfo &HI) {
1028+
HI.Name = "x";
1029+
HI.Kind = index::SymbolKind::Variable;
1030+
HI.NamespaceScope = "";
1031+
HI.Definition = "const int x = 0";
1032+
HI.LocalScope = "bar::";
1033+
HI.Value = "0";
1034+
HI.Type = "const int";
1035+
HI.CalleeArgInfo.emplace();
1036+
HI.CalleeArgInfo->Type = "Foo";
1037+
HI.CallPassType = HoverInfo::PassType{PassMode::ConstRef, true};
1038+
}},
9631039
{// Dont crash on invalid decl
9641040
R"cpp(
9651041
// error-ok
@@ -1673,8 +1749,8 @@ TEST(Hover, All) {
16731749
}},
16741750
{
16751751
R"cpp(// Function definition via using declaration
1676-
namespace ns {
1677-
void foo();
1752+
namespace ns {
1753+
void foo();
16781754
}
16791755
int main() {
16801756
using ns::foo;

0 commit comments

Comments
 (0)