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 QT) { + if (QT->isReferenceType()) { + if (QT->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,18 @@ if (!FD || FD->isOverloadedOperator() || FD->isVariadic()) return; + QualType ParmType; + // 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)); + ParmType = PVD->getType(); + } break; } if (!HI.CalleeArgInfo) @@ -989,15 +1002,7 @@ // [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; - } - + PassType.PassBy = getPassMode(ParmType); for (auto *CastNode = N->Parent; CastNode != OuterNode.Parent && !PassType.Converted; CastNode = CastNode->Parent) { @@ -1006,22 +1011,13 @@ case CK_NoOp: case CK_DerivedToBase: case CK_UncheckedDerivedToBase: - // If it was a reference before, it's still a reference. - if (PassType.PassBy != HoverInfo::PassType::Value) - PassType.PassBy = ImplicitCast->getType().isConstQualified() - ? HoverInfo::PassType::ConstRef - : HoverInfo::PassType::Ref; - break; case CK_LValueToRValue: case CK_ArrayToPointerDecay: case CK_FunctionToPointerDecay: case CK_NullToPointer: case CK_NullToMemberPointer: - // No longer a reference, but we do not show this as type conversion. - PassType.PassBy = HoverInfo::PassType::Value; break; default: - PassType.PassBy = HoverInfo::PassType::Value; PassType.Converted = true; break; } @@ -1029,16 +1025,16 @@ CastNode->ASTNode.get()) { // We want to be smart about copy constructors. They should not show up as // type conversion, but instead as passing by value. - if (CtorCall->getConstructor()->isCopyConstructor()) + const CXXConstructorDecl *CD = CtorCall->getConstructor(); + if (CD->isCopyConstructor()) { PassType.PassBy = HoverInfo::PassType::Value; - else + } else { + PassType.PassBy = getPassMode(CD->getParamDecl(0)->getType()); PassType.Converted = true; + } } else if (const auto *MTE = CastNode->ASTNode.get()) { - // Can't bind a non-const-ref to a temporary, so has to be const-ref - PassType.PassBy = HoverInfo::PassType::ConstRef; } else { // Unknown implicit node, assume type conversion. - PassType.PassBy = HoverInfo::PassType::Value; PassType.Converted = true; } } @@ -1068,9 +1064,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 @@ -934,6 +934,23 @@ 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}; + }}, {// Extra info for method call. R"cpp( class C { @@ -1673,8 +1690,8 @@ }}, { R"cpp(// Function definition via using declaration - namespace ns { - void foo(); + namespace ns { + void foo(); } int main() { using ns::foo;