[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
This commit is contained in:
Balázs Kéri 2021-04-12 08:52:40 +02:00
parent d69c236e1d
commit 6e51991049
2 changed files with 74 additions and 0 deletions

View file

@ -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>();

View file

@ -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