nridge updated this revision to Diff 551390.
nridge added a comment.

Fix naming nit


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D158249/new/

https://reviews.llvm.org/D158249

Files:
  clang-tools-extra/clangd/InlayHints.cpp
  clang-tools-extra/clangd/unittests/InlayHintTests.cpp

Index: clang-tools-extra/clangd/unittests/InlayHintTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/InlayHintTests.cpp
+++ clang-tools-extra/clangd/unittests/InlayHintTests.cpp
@@ -910,6 +910,26 @@
   )cpp");
 }
 
+TEST(ParameterHints, FunctionPointer) {
+  assertParameterHints(
+      R"cpp(
+    void (*f1)(int param);
+    void (__stdcall *f2)(int param);
+    using f3_t = void(*)(int param);
+    f3_t f3;
+    using f4_t = void(__stdcall *)(int param);
+    f4_t f4;
+    void bar() {
+      f1($f1[[42]]);
+      f2($f2[[42]]);
+      f3($f3[[42]]);
+      f4($f4[[42]]);
+    }
+  )cpp",
+      ExpectedHint{"param: ", "f1"}, ExpectedHint{"param: ", "f2"},
+      ExpectedHint{"param: ", "f3"}, ExpectedHint{"param: ", "f4"});
+}
+
 TEST(ParameterHints, ArgMatchesParam) {
   assertParameterHints(R"cpp(
     void foo(int param);
Index: clang-tools-extra/clangd/InlayHints.cpp
===================================================================
--- clang-tools-extra/clangd/InlayHints.cpp
+++ clang-tools-extra/clangd/InlayHints.cpp
@@ -460,6 +460,58 @@
   return QT;
 }
 
+// Given a callee expression `Fn`, if the call is through a function pointer,
+// try to find the declaration of the corresponding function pointer type,
+// so that we can recover argument names from it.
+// FIXME: This function is mostly duplicated in SemaCodeComplete.cpp; unify.
+static FunctionProtoTypeLoc getPrototypeLoc(Expr *Fn) {
+  TypeLoc Target;
+  Expr *NakedFn = Fn->IgnoreParenCasts();
+  if (const auto *T = NakedFn->getType().getTypePtr()->getAs<TypedefType>()) {
+    Target = T->getDecl()->getTypeSourceInfo()->getTypeLoc();
+  } else if (const auto *DR = dyn_cast<DeclRefExpr>(NakedFn)) {
+    const auto *D = DR->getDecl();
+    if (const auto *const VD = dyn_cast<VarDecl>(D)) {
+      Target = VD->getTypeSourceInfo()->getTypeLoc();
+    }
+  }
+
+  if (!Target)
+    return {};
+
+  // Unwrap types that may be wrapping the function type
+  while (true) {
+    if (auto P = Target.getAs<PointerTypeLoc>()) {
+      Target = P.getPointeeLoc();
+      continue;
+    }
+    if (auto A = Target.getAs<AttributedTypeLoc>()) {
+      Target = A.getModifiedLoc();
+      continue;
+    }
+    if (auto P = Target.getAs<ParenTypeLoc>()) {
+      Target = P.getInnerLoc();
+      continue;
+    }
+    break;
+  }
+
+  if (auto F = Target.getAs<FunctionProtoTypeLoc>()) {
+    return F;
+  }
+
+  return {};
+}
+
+struct CallInfo {
+  // Only one of Callee or ProtoTypeLoc is set.
+  const FunctionDecl *Callee = nullptr;
+  FunctionProtoTypeLoc ProtoTypeLoc;
+
+  // Args is always set.
+  llvm::ArrayRef<const Expr *> Args;
+};
+
 class InlayHintVisitor : public RecursiveASTVisitor<InlayHintVisitor> {
 public:
   InlayHintVisitor(std::vector<InlayHint> &Results, ParsedAST &AST,
@@ -499,7 +551,12 @@
       return true;
     }
 
-    processCall(E->getConstructor(), {E->getArgs(), E->getNumArgs()});
+    CallInfo Call;
+    Call.Callee = E->getConstructor();
+    if (!Call.Callee)
+      return true;
+    Call.Args = {E->getArgs(), E->getNumArgs()};
+    processCall(Call);
     return true;
   }
 
@@ -522,10 +579,17 @@
       Callee = FD;
     else if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(CalleeDecls[0]))
       Callee = FTD->getTemplatedDecl();
-    if (!Callee)
-      return true;
 
-    processCall(Callee, {E->getArgs(), E->getNumArgs()});
+    CallInfo Call;
+    if (Callee)
+      Call.Callee = Callee;
+    else if (FunctionProtoTypeLoc ProtoTypeLoc =
+                 getPrototypeLoc(E->getCallee()))
+      Call.ProtoTypeLoc = ProtoTypeLoc;
+    else
+      return true;
+    Call.Args = {E->getArgs(), E->getNumArgs()};
+    processCall(Call);
     return true;
   }
 
@@ -737,42 +801,51 @@
 private:
   using NameVec = SmallVector<StringRef, 8>;
 
-  void processCall(const FunctionDecl *Callee,
-                   llvm::ArrayRef<const Expr *> Args) {
-    if (!Cfg.InlayHints.Parameters || Args.size() == 0 || !Callee)
+  void processCall(CallInfo Call) {
+    assert(Call.Callee || Call.ProtoTypeLoc);
+
+    if (!Cfg.InlayHints.Parameters || Call.Args.size() == 0)
       return;
 
     // The parameter name of a move or copy constructor is not very interesting.
-    if (auto *Ctor = dyn_cast<CXXConstructorDecl>(Callee))
-      if (Ctor->isCopyOrMoveConstructor())
-        return;
+    if (Call.Callee)
+      if (auto *Ctor = dyn_cast<CXXConstructorDecl>(Call.Callee))
+        if (Ctor->isCopyOrMoveConstructor())
+          return;
+
+    auto Params =
+        Call.Callee ? Call.Callee->parameters() : Call.ProtoTypeLoc.getParams();
 
     // Resolve parameter packs to their forwarded parameter
-    auto ForwardedParams = resolveForwardingParameters(Callee);
+    SmallVector<const ParmVarDecl *> ForwardedParams;
+    if (Call.Callee)
+      ForwardedParams = resolveForwardingParameters(Call.Callee);
+    else
+      ForwardedParams = {Params.begin(), Params.end()};
 
     NameVec ParameterNames = chooseParameterNames(ForwardedParams);
 
     // Exclude setters (i.e. functions with one argument whose name begins with
     // "set"), and builtins like std::move/forward/... as their parameter name
     // is also not likely to be interesting.
-    if (isSetter(Callee, ParameterNames) || isSimpleBuiltin(Callee))
+    if (Call.Callee &&
+        (isSetter(Call.Callee, ParameterNames) || isSimpleBuiltin(Call.Callee)))
       return;
 
-    for (size_t I = 0; I < ParameterNames.size() && I < Args.size(); ++I) {
+    for (size_t I = 0; I < ParameterNames.size() && I < Call.Args.size(); ++I) {
       // Pack expansion expressions cause the 1:1 mapping between arguments and
       // parameters to break down, so we don't add further inlay hints if we
       // encounter one.
-      if (isa<PackExpansionExpr>(Args[I])) {
+      if (isa<PackExpansionExpr>(Call.Args[I])) {
         break;
       }
 
       StringRef Name = ParameterNames[I];
-      bool NameHint = shouldHintName(Args[I], Name);
-      bool ReferenceHint =
-          shouldHintReference(Callee->getParamDecl(I), ForwardedParams[I]);
+      bool NameHint = shouldHintName(Call.Args[I], Name);
+      bool ReferenceHint = shouldHintReference(Params[I], ForwardedParams[I]);
 
       if (NameHint || ReferenceHint) {
-        addInlayHint(Args[I]->getSourceRange(), HintSide::Left,
+        addInlayHint(Call.Args[I]->getSourceRange(), HintSide::Left,
                      InlayHintKind::Parameter, ReferenceHint ? "&" : "",
                      NameHint ? Name : "", ": ");
       }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to