Author: Balázs Kéri Date: 2021-04-12T09:44:17+02:00 New Revision: 6e5199104914c2415092315388ed09fbd9d629f7
URL: https://github.com/llvm/llvm-project/commit/6e5199104914c2415092315388ed09fbd9d629f7 DIFF: https://github.com/llvm/llvm-project/commit/6e5199104914c2415092315388ed09fbd9d629f7.diff LOG: [clang][AST] Handle overload callee type in CallExpr::getCallReturnType. The function did not handle every case. In some cases this caused assertion failure. After the fix the function returns DependentTy if the exact return type can not be determined. It seems that clang itself does not call the function in the affected cases but some checker or other code may call it. Reviewed By: hokein Differential Revision: https://reviews.llvm.org/D95244 Added: Modified: clang/lib/AST/Expr.cpp clang/unittests/Tooling/SourceCodeTest.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index eccb42eeb7e74..a4a70befbdb31 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1391,8 +1391,15 @@ QualType CallExpr::getCallReturnType(const ASTContext &Ctx) const { if (isa<CXXPseudoDestructorExpr>(Callee->IgnoreParens())) return Ctx.VoidTy; + if (isa<UnresolvedMemberExpr>(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<FunctionType>(); diff --git a/clang/unittests/Tooling/SourceCodeTest.cpp b/clang/unittests/Tooling/SourceCodeTest.cpp index eb652cf030644..badc6f88fc0af 100644 --- a/clang/unittests/Tooling/SourceCodeTest.cpp +++ b/clang/unittests/Tooling/SourceCodeTest.cpp @@ -621,4 +621,71 @@ int c = BAR 3.0; }; Visitor.runOver(Code); } + +TEST(SourceCodeTest, GetCallReturnType_Dependent) { + llvm::Annotations Code{R"cpp( +template<class T, class F> +void templ(const T& t, F f) {} + +template<class T, class F> +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<UnresolvedLookupExpr>(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<UnresolvedMemberExpr>(Expr->getCallee())); + EXPECT_EQ(Expr->getCallReturnType(*Context), Context->DependentTy); + } + }; + Visitor.runOver(Code.code(), CallsVisitor::Lang_CXX14); +} + } // end anonymous namespace _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits