forked from OSchip/llvm-project
Provide suggested no-arg calls for overloaded member functions missing calls
Reviewed by Richard Smith. llvm-svn: 184612
This commit is contained in:
parent
4c280bd3de
commit
e5323aa921
|
@ -3083,8 +3083,8 @@ public:
|
|||
bool (*IsPlausibleResult)(QualType) = 0);
|
||||
|
||||
/// \brief Figure out if an expression could be turned into a call.
|
||||
bool isExprCallable(const Expr &E, QualType &ZeroArgCallReturnTy,
|
||||
UnresolvedSetImpl &NonTemplateOverloads);
|
||||
bool tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
|
||||
UnresolvedSetImpl &NonTemplateOverloads);
|
||||
|
||||
/// \brief Conditionally issue a diagnostic based on the current
|
||||
/// evaluation context.
|
||||
|
|
|
@ -1136,12 +1136,13 @@ void PrettyDeclStackTraceEntry::print(raw_ostream &OS) const {
|
|||
/// call; otherwise, it is set to an empty QualType.
|
||||
/// \param OverloadSet - If the expression is an overloaded function
|
||||
/// name, this parameter is populated with the decls of the various overloads.
|
||||
bool Sema::isExprCallable(const Expr &E, QualType &ZeroArgCallReturnTy,
|
||||
UnresolvedSetImpl &OverloadSet) {
|
||||
bool Sema::tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy,
|
||||
UnresolvedSetImpl &OverloadSet) {
|
||||
ZeroArgCallReturnTy = QualType();
|
||||
OverloadSet.clear();
|
||||
|
||||
const OverloadExpr *Overloads = NULL;
|
||||
bool IsMemExpr = false;
|
||||
if (E.getType() == Context.OverloadTy) {
|
||||
OverloadExpr::FindResult FR = OverloadExpr::find(const_cast<Expr*>(&E));
|
||||
|
||||
|
@ -1152,15 +1153,20 @@ bool Sema::isExprCallable(const Expr &E, QualType &ZeroArgCallReturnTy,
|
|||
Overloads = FR.Expression;
|
||||
} else if (E.getType() == Context.BoundMemberTy) {
|
||||
Overloads = dyn_cast<UnresolvedMemberExpr>(E.IgnoreParens());
|
||||
IsMemExpr = true;
|
||||
}
|
||||
|
||||
bool Ambiguous = false;
|
||||
|
||||
if (Overloads) {
|
||||
bool Ambiguous = false;
|
||||
for (OverloadExpr::decls_iterator it = Overloads->decls_begin(),
|
||||
DeclsEnd = Overloads->decls_end(); it != DeclsEnd; ++it) {
|
||||
OverloadSet.addDecl(*it);
|
||||
|
||||
// Check whether the function is a non-template which takes no
|
||||
// Check whether the function is a non-template, non-member which takes no
|
||||
// arguments.
|
||||
if (IsMemExpr)
|
||||
continue;
|
||||
if (const FunctionDecl *OverloadDecl
|
||||
= dyn_cast<FunctionDecl>((*it)->getUnderlyingDecl())) {
|
||||
if (OverloadDecl->getMinRequiredArguments() == 0) {
|
||||
|
@ -1173,7 +1179,25 @@ bool Sema::isExprCallable(const Expr &E, QualType &ZeroArgCallReturnTy,
|
|||
}
|
||||
}
|
||||
|
||||
return !Ambiguous;
|
||||
// If it's not a member, use better machinery to try to resolve the call
|
||||
if (!IsMemExpr)
|
||||
return !ZeroArgCallReturnTy.isNull();
|
||||
}
|
||||
|
||||
// Attempt to call the member with no arguments - this will correctly handle
|
||||
// member templates with defaults/deduction of template arguments, overloads
|
||||
// with default arguments, etc.
|
||||
if (IsMemExpr) {
|
||||
bool Suppress = getDiagnostics().getSuppressAllDiagnostics();
|
||||
getDiagnostics().setSuppressAllDiagnostics(true);
|
||||
ExprResult R = BuildCallToMemberFunction(NULL, &E, SourceLocation(), None,
|
||||
SourceLocation());
|
||||
getDiagnostics().setSuppressAllDiagnostics(Suppress);
|
||||
if (R.isUsable()) {
|
||||
ZeroArgCallReturnTy = R.get()->getType();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (const DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(E.IgnoreParens())) {
|
||||
|
@ -1193,14 +1217,6 @@ bool Sema::isExprCallable(const Expr &E, QualType &ZeroArgCallReturnTy,
|
|||
FunTy = PointeeTy->getAs<FunctionType>();
|
||||
if (!FunTy)
|
||||
FunTy = ExprTy->getAs<FunctionType>();
|
||||
if (!FunTy && ExprTy == Context.BoundMemberTy) {
|
||||
// Look for the bound-member type. If it's still overloaded, give up,
|
||||
// although we probably should have fallen into the OverloadExpr case above
|
||||
// if we actually have an overloaded bound member.
|
||||
QualType BoundMemberTy = Expr::findBoundMemberType(&E);
|
||||
if (!BoundMemberTy.isNull())
|
||||
FunTy = BoundMemberTy->castAs<FunctionType>();
|
||||
}
|
||||
|
||||
if (const FunctionProtoType *FPT =
|
||||
dyn_cast_or_null<FunctionProtoType>(FunTy)) {
|
||||
|
@ -1213,7 +1229,7 @@ bool Sema::isExprCallable(const Expr &E, QualType &ZeroArgCallReturnTy,
|
|||
|
||||
/// \brief Give notes for a set of overloads.
|
||||
///
|
||||
/// A companion to isExprCallable. In cases when the name that the programmer
|
||||
/// A companion to tryExprAsCall. In cases when the name that the programmer
|
||||
/// wrote was an overloaded function, we may be able to make some guesses about
|
||||
/// plausible overloads based on their return types; such guesses can be handed
|
||||
/// off to this method to be emitted as notes.
|
||||
|
@ -1283,7 +1299,7 @@ bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD,
|
|||
|
||||
QualType ZeroArgCallTy;
|
||||
UnresolvedSet<4> Overloads;
|
||||
if (isExprCallable(*E.get(), ZeroArgCallTy, Overloads) &&
|
||||
if (tryExprAsCall(*E.get(), ZeroArgCallTy, Overloads) &&
|
||||
!ZeroArgCallTy.isNull() &&
|
||||
(!IsPlausibleResult || IsPlausibleResult(ZeroArgCallTy))) {
|
||||
// At this point, we know E is potentially callable with 0
|
||||
|
|
|
@ -4871,7 +4871,7 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
|
|||
<< FixItHint::CreateInsertion(E->getExprLoc(), "&");
|
||||
QualType ReturnType;
|
||||
UnresolvedSet<4> NonTemplateOverloads;
|
||||
S.isExprCallable(*E, ReturnType, NonTemplateOverloads);
|
||||
S.tryExprAsCall(*E, ReturnType, NonTemplateOverloads);
|
||||
if (!ReturnType.isNull()
|
||||
&& ReturnType->isSpecificBuiltinType(BuiltinType::Bool))
|
||||
S.Diag(E->getExprLoc(), diag::note_function_to_bool_call)
|
||||
|
|
|
@ -57,7 +57,7 @@ struct B
|
|||
|
||||
struct C {
|
||||
C &getC() {
|
||||
return makeAC; // expected-error-re{{reference to non-static member function must be called$}}
|
||||
return makeAC; // expected-error{{reference to non-static member function must be called; did you mean to call it with no arguments?}}
|
||||
}
|
||||
|
||||
// FIXME: filter by const so we can unambiguously suggest '()' & point to just the one candidate, probably
|
||||
|
@ -70,6 +70,32 @@ struct C {
|
|||
void g() {
|
||||
int (&fp)() = f; // expected-error{{address of overloaded function 'f' does not match required type 'int ()'}}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void q1(int); // expected-note{{possible target for call}}
|
||||
template<typename T>
|
||||
void q2(T t = T()); // expected-note{{possible target for call}}
|
||||
template<typename T>
|
||||
void q3(); // expected-note{{possible target for call}}
|
||||
template<typename T1, typename T2>
|
||||
void q4(); // expected-note{{possible target for call}}
|
||||
template<typename T1 = int> // expected-warning{{default template arguments for a function template are a C++11 extension}}
|
||||
void q5(); // expected-note{{possible target for call}}
|
||||
|
||||
void h() {
|
||||
// Do not suggest '()' since an int argument is required
|
||||
q1<int>; // expected-error-re{{reference to non-static member function must be called$}}
|
||||
// Suggest '()' since there's a default value for the only argument & the
|
||||
// type argument is already provided
|
||||
q2<int>; // expected-error{{reference to non-static member function must be called; did you mean to call it with no arguments?}}
|
||||
// Suggest '()' since no arguments are required & the type argument is
|
||||
// already provided
|
||||
q3<int>; // expected-error{{reference to non-static member function must be called; did you mean to call it with no arguments?}}
|
||||
// Do not suggest '()' since another type argument is required
|
||||
q4<int>; // expected-error-re{{reference to non-static member function must be called$}}
|
||||
// Suggest '()' since the type parameter has a default value
|
||||
q5; // expected-error{{reference to non-static member function must be called; did you mean to call it with no arguments?}}
|
||||
}
|
||||
};
|
||||
|
||||
// PR6886
|
||||
|
|
Loading…
Reference in New Issue