aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/Sema/SemaCodeComplete.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/Sema/SemaCodeComplete.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/Sema/SemaCodeComplete.cpp72
1 files changed, 57 insertions, 15 deletions
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaCodeComplete.cpp b/contrib/llvm-project/clang/lib/Sema/SemaCodeComplete.cpp
index 86bad736227d..8ede7c015315 100644
--- a/contrib/llvm-project/clang/lib/Sema/SemaCodeComplete.cpp
+++ b/contrib/llvm-project/clang/lib/Sema/SemaCodeComplete.cpp
@@ -53,6 +53,7 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
+
#include <list>
#include <map>
#include <string>
@@ -3722,13 +3723,11 @@ static void AddOverloadAggregateChunks(const RecordDecl *RD,
/// Add function overload parameter chunks to the given code completion
/// string.
-static void AddOverloadParameterChunks(ASTContext &Context,
- const PrintingPolicy &Policy,
- const FunctionDecl *Function,
- const FunctionProtoType *Prototype,
- CodeCompletionBuilder &Result,
- unsigned CurrentArg, unsigned Start = 0,
- bool InOptional = false) {
+static void AddOverloadParameterChunks(
+ ASTContext &Context, const PrintingPolicy &Policy,
+ const FunctionDecl *Function, const FunctionProtoType *Prototype,
+ FunctionProtoTypeLoc PrototypeLoc, CodeCompletionBuilder &Result,
+ unsigned CurrentArg, unsigned Start = 0, bool InOptional = false) {
if (!Function && !Prototype) {
Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
return;
@@ -3747,8 +3746,9 @@ static void AddOverloadParameterChunks(ASTContext &Context,
if (!FirstParameter)
Opt.AddChunk(CodeCompletionString::CK_Comma);
// Optional sections are nested.
- AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt,
- CurrentArg, P, /*InOptional=*/true);
+ AddOverloadParameterChunks(Context, Policy, Function, Prototype,
+ PrototypeLoc, Opt, CurrentArg, P,
+ /*InOptional=*/true);
Result.AddOptionalChunk(Opt.TakeString());
return;
}
@@ -3762,8 +3762,10 @@ static void AddOverloadParameterChunks(ASTContext &Context,
// Format the placeholder string.
std::string Placeholder;
- if (Function) {
- const ParmVarDecl *Param = Function->getParamDecl(P);
+ assert(P < Prototype->getNumParams());
+ if (Function || PrototypeLoc) {
+ const ParmVarDecl *Param =
+ Function ? Function->getParamDecl(P) : PrototypeLoc.getParam(P);
Placeholder = FormatFunctionParameter(Policy, Param);
if (Param->hasDefaultArg())
Placeholder += GetDefaultValueString(Param, Context.getSourceManager(),
@@ -3916,8 +3918,8 @@ CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
if (getKind() == CK_Aggregate)
AddOverloadAggregateChunks(getAggregate(), Policy, Result, CurrentArg);
else
- AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result,
- CurrentArg);
+ AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto,
+ getFunctionProtoTypeLoc(), Result, CurrentArg);
Result.AddChunk(Braced ? CodeCompletionString::CK_RightBrace
: CodeCompletionString::CK_RightParen);
@@ -5998,6 +6000,39 @@ ProduceSignatureHelp(Sema &SemaRef, MutableArrayRef<ResultCandidate> Candidates,
return getParamType(SemaRef, Candidates, CurrentArg);
}
+// 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.
+static FunctionProtoTypeLoc GetPrototypeLoc(Expr *Fn) {
+ TypeLoc Target;
+ if (const auto *T = Fn->getType().getTypePtr()->getAs<TypedefType>()) {
+ Target = T->getDecl()->getTypeSourceInfo()->getTypeLoc();
+
+ } else if (const auto *DR = dyn_cast<DeclRefExpr>(Fn)) {
+ const auto *D = DR->getDecl();
+ if (const auto *const VD = dyn_cast<VarDecl>(D)) {
+ Target = VD->getTypeSourceInfo()->getTypeLoc();
+ }
+ }
+
+ if (!Target)
+ return {};
+
+ if (auto P = Target.getAs<PointerTypeLoc>()) {
+ Target = P.getPointeeLoc();
+ }
+
+ if (auto P = Target.getAs<ParenTypeLoc>()) {
+ Target = P.getInnerLoc();
+ }
+
+ if (auto F = Target.getAs<FunctionProtoTypeLoc>()) {
+ return F;
+ }
+
+ return {};
+}
+
QualType Sema::ProduceCallSignatureHelp(Expr *Fn, ArrayRef<Expr *> Args,
SourceLocation OpenParLoc) {
Fn = unwrapParenList(Fn);
@@ -6079,6 +6114,8 @@ QualType Sema::ProduceCallSignatureHelp(Expr *Fn, ArrayRef<Expr *> Args,
} else {
// Lastly we check whether expression's type is function pointer or
// function.
+
+ FunctionProtoTypeLoc P = GetPrototypeLoc(NakedFn);
QualType T = NakedFn->getType();
if (!T->getPointeeType().isNull())
T = T->getPointeeType();
@@ -6087,8 +6124,13 @@ QualType Sema::ProduceCallSignatureHelp(Expr *Fn, ArrayRef<Expr *> Args,
if (!TooManyArguments(FP->getNumParams(),
ArgsWithoutDependentTypes.size(),
/*PartialOverloading=*/true) ||
- FP->isVariadic())
- Results.push_back(ResultCandidate(FP));
+ FP->isVariadic()) {
+ if (P) {
+ Results.push_back(ResultCandidate(P));
+ } else {
+ Results.push_back(ResultCandidate(FP));
+ }
+ }
} else if (auto FT = T->getAs<FunctionType>())
// No prototype and declaration, it may be a K & R style function.
Results.push_back(ResultCandidate(FT));