/// 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));
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) {
}
}
- 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())) {
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)) {
/// \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.
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
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
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