diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 46 | ||||
-rw-r--r-- | clang/lib/Sema/SemaChecking.cpp | 2 |
2 files changed, 32 insertions, 16 deletions
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 954091d6177..3ddce77a883 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -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 diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 87fe7635891..96d8742b91d 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -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) |