diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1391,8 +1391,15 @@ if (isa(Callee->IgnoreParens())) return Ctx.VoidTy; + if (isa(Callee->IgnoreParens())) + return Ctx.DependentTy; + // This should never be overloaded and so should never return null. CalleeType = Expr::findBoundMemberType(Callee); + assert(!CalleeType.isNull()); + } else if (CalleeType->isDependentType() || + CalleeType->isSpecificPlaceholderType(BuiltinType::Overload)) { + return Ctx.DependentTy; } const FunctionType *FnType = CalleeType->castAs(); diff --git a/clang/unittests/Tooling/SourceCodeTest.cpp b/clang/unittests/Tooling/SourceCodeTest.cpp --- a/clang/unittests/Tooling/SourceCodeTest.cpp +++ b/clang/unittests/Tooling/SourceCodeTest.cpp @@ -621,4 +621,71 @@ }; Visitor.runOver(Code); } + +TEST(SourceCodeTest, GetCallReturnType_Dependent) { + llvm::Annotations Code{R"cpp( +template +void templ(const T& t, F f) {} + +template +void templ1(const T& t, F f) { + $test1[[f(t)]]; +} + +int f_overload(int) { return 1; } +int f_overload(double) { return 2; } + +void f1() { + int i = 0; + templ(i, [](const auto &p) { + $test2[[f_overload(p)]]; + }); +} + +struct A { + void f_overload(int); + void f_overload(double); +}; + +void f2() { + int i = 0; + templ(i, [](const auto &p) { + A a; + $test3[[a.f_overload(p)]]; + }); +} +)cpp"}; + + llvm::Annotations::Range R1 = Code.range("test1"); + llvm::Annotations::Range R2 = Code.range("test2"); + llvm::Annotations::Range R3 = Code.range("test3"); + + CallsVisitor Visitor; + Visitor.OnCall = [&R1, &R2, &R3](CallExpr *Expr, ASTContext *Context) { + unsigned Begin = Context->getSourceManager().getFileOffset( + Expr->getSourceRange().getBegin()); + unsigned End = Context->getSourceManager().getFileOffset( + Expr->getSourceRange().getEnd()); + llvm::Annotations::Range R{Begin, End + 1}; + + QualType CalleeType = Expr->getCallee()->getType(); + if (R == R1) { + ASSERT_TRUE(CalleeType->isDependentType()); + EXPECT_EQ(Expr->getCallReturnType(*Context), Context->DependentTy); + } else if (R == R2) { + ASSERT_FALSE(CalleeType->isDependentType()); + ASSERT_TRUE(CalleeType->isSpecificPlaceholderType(BuiltinType::Overload)); + ASSERT_TRUE(isa(Expr->getCallee())); + EXPECT_EQ(Expr->getCallReturnType(*Context), Context->DependentTy); + } else if (R == R3) { + ASSERT_FALSE(CalleeType->isDependentType()); + ASSERT_TRUE( + CalleeType->isSpecificPlaceholderType(BuiltinType::BoundMember)); + ASSERT_TRUE(isa(Expr->getCallee())); + EXPECT_EQ(Expr->getCallReturnType(*Context), Context->DependentTy); + } + }; + Visitor.runOver(Code.code(), CallsVisitor::Lang_CXX14); +} + } // end anonymous namespace