diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp index dd6ee44224471..671c0b7da97c6 100644 --- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp +++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp @@ -1397,20 +1397,37 @@ TEST(SignatureHelpTest, Overloads) { } TEST(SignatureHelpTest, FunctionPointers) { - auto FunctionPointerResults = signatures(R"cpp( + llvm::StringLiteral Tests[] = { + // Variable of function pointer type + R"cpp( void (*foo)(int x, int y); int main() { foo(^); } - )cpp"); - EXPECT_THAT(FunctionPointerResults.signatures, - UnorderedElementsAre(sig("([[int x]], [[int y]]) -> void"))); - - auto FunctionPointerTypedefResults = signatures(R"cpp( + )cpp", + // Wrapped in an AttributedType + R"cpp( + void (__stdcall *foo)(int x, int y); + int main() { foo(^); } + )cpp", + // Another syntax for an AttributedType + R"cpp( + void (__attribute__(stdcall) *foo)(int x, int y); + int main() { foo(^); }, + )cpp", + // Wrapped in a typedef + R"cpp( typedef void (*fn)(int x, int y); fn foo; int main() { foo(^); } - )cpp"); - EXPECT_THAT(FunctionPointerTypedefResults.signatures, - UnorderedElementsAre(sig("([[int x]], [[int y]]) -> void"))); + )cpp", + // Wrapped in both a typedef and an AttributedTyped + R"cpp( + typedef void (__stdcall *fn)(int x, int y); + fn foo; + int main() { foo(^); } + )cpp"}; + for (auto Test : Tests) + EXPECT_THAT(signatures(Test).signatures, + UnorderedElementsAre(sig("([[int x]], [[int y]]) -> void"))); } TEST(SignatureHelpTest, Constructors) { diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index b9760e8e74452..e3a2a21386e72 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -6066,12 +6066,21 @@ static FunctionProtoTypeLoc GetPrototypeLoc(Expr *Fn) { if (!Target) return {}; - if (auto P = Target.getAs()) { - Target = P.getPointeeLoc(); - } - - if (auto P = Target.getAs()) { - Target = P.getInnerLoc(); + // Unwrap types that may be wrapping the function type + while (true) { + if (auto P = Target.getAs()) { + Target = P.getPointeeLoc(); + continue; + } + if (auto A = Target.getAs()) { + Target = A.getModifiedLoc(); + continue; + } + if (auto P = Target.getAs()) { + Target = P.getInnerLoc(); + continue; + } + break; } if (auto F = Target.getAs()) {