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 @@ -1382,6 +1382,14 @@ QualType CallExpr::getCallReturnType(const ASTContext &Ctx) const { const Expr *Callee = getCallee(); QualType CalleeType = Callee->getType(); + + auto CreateDependentType = [&Ctx]() { + ASTContext::GetBuiltinTypeError Error; + QualType RetTy = Ctx.GetBuiltinType(BuiltinType::Dependent, Error); + assert(Error == ASTContext::GE_None); + return RetTy; + }; + if (const auto *FnTypePtr = CalleeType->getAs()) { CalleeType = FnTypePtr->getPointeeType(); } else if (const auto *BPT = CalleeType->getAs()) { @@ -1390,8 +1398,13 @@ if (isa(Callee->IgnoreParens())) return Ctx.VoidTy; - // This should never be overloaded and so should never return null. CalleeType = Expr::findBoundMemberType(Callee); + if (CalleeType.isNull()) + return CreateDependentType(); + + } else if (CalleeType->isDependentType() || + CalleeType->isSpecificPlaceholderType(BuiltinType::Overload)) { + return CreateDependentType(); } 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,37 @@ }; Visitor.runOver(Code); } + +TEST(SourceCodeTest, GetCallReturnType) { + llvm::StringRef Code = R"cpp( +template +void templ(const T& t, F f) { + f(t); +} +int f_overload(int) { return 1; } +int f_overload(double) { return 2; } + +struct A { + void f(int); + void f(double); +}; + +void f() { + int i = 0; + templ(i, [](const auto &p) { + f_overload(p); + A a; + a.f(p); + }); +} +)cpp"; + + CallsVisitor Visitor; + Visitor.OnCall = [](CallExpr *Expr, ASTContext *Context) { + // Should not crash. + (void)Expr->getCallReturnType(*Context); + }; + Visitor.runOver(Code, CallsVisitor::Lang_CXX14); +} + } // end anonymous namespace