From: John McCall Date: Tue, 11 Oct 2011 23:14:30 +0000 (+0000) Subject: Catch placeholder types in DefaultLvalueConversion X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6dbba4fc128e2e2f5b26be996392bd32c0707f13;p=clang Catch placeholder types in DefaultLvalueConversion and DefaultFunctionArrayLvalueConversion. To prevent significant regression for should-this-be-a-call fixits, and to repair some such regression from the introduction of bound member placeholders, make those placeholder checks try to build calls appropriately. Harden the build-a-call logic while we're at it. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141738 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 240401b393..3e652ba1ec 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1977,9 +1977,13 @@ def err_ovl_no_viable_subscript : Error<"no viable overloaded operator[] for type %0">; def err_ovl_no_oper : Error<"type %0 does not provide a %select{subscript|call}1 operator">; -def err_ovl_unresolvable : - Error<"cannot resolve overloaded function %0 from context">; - +def err_ovl_unresolvable : Error< + "reference to overloaded function could not be resolved; " + "did you mean to call it%select{| with no arguments}0?">; +def err_bound_member_function : Error< + "reference to non-static member function must be called" + "%select{|; did you mean to call it with no arguments?}0">; +def note_possible_target_of_call : Note<"possible target for call">; def err_ovl_no_viable_object_call : Error< "no matching function for call to object of type %0">; @@ -3211,10 +3215,8 @@ def err_typecheck_member_reference_type : Error< def err_typecheck_member_reference_unknown : Error< "cannot refer to member %0 in %1 with '%select{.|->}2'">; def err_member_reference_needs_call : Error< - "base of member reference is %select{a function|an overloaded function}0; " - "perhaps you meant to call it%select{| with no arguments}1?">; -def note_member_ref_possible_intended_overload : Note< - "possibly valid overload here">; + "base of member reference is a function; perhaps you meant to call " + "it%select{| with no arguments}?">; def warn_subscript_is_char : Warning<"array subscript is of type 'char'">, InGroup, DefaultIgnore; @@ -3804,8 +3806,6 @@ def err_not_tag_in_scope : Error< def err_cannot_form_pointer_to_member_of_reference_type : Error< "cannot form a pointer-to-member to member %0 of reference type %1">; -def err_invalid_use_of_bound_member_func : Error< - "a bound member function may only be called">; def err_incomplete_object_call : Error< "incomplete type in call to object of type %0">; def err_incomplete_pointer_to_member_return : Error< diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 9bb4022ab7..32bdc73d04 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -1554,8 +1554,9 @@ public: bool Complain = false, DeclAccessPair* Found = 0); - ExprResult ResolveAndFixSingleFunctionTemplateSpecialization( - Expr *SrcExpr, bool DoFunctionPointerConverion = false, + bool ResolveAndFixSingleFunctionTemplateSpecialization( + ExprResult &SrcExpr, + bool DoFunctionPointerConverion = false, bool Complain = false, const SourceRange& OpRangeForComplaining = SourceRange(), QualType DestTypeForComplaining = QualType(), @@ -2274,12 +2275,16 @@ public: void MarkDeclarationsReferencedInType(SourceLocation Loc, QualType T); void MarkDeclarationsReferencedInExpr(Expr *E); + /// \brief Try to recover by turning the given expression into a + /// call. Returns true if recovery was attempted or an error was + /// emitted; this may also leave the ExprResult invalid. + bool tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD, + bool ForceComplain = false, + 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); - /// \brief Give notes for a set of overloads. - void NoteOverloads(const UnresolvedSetImpl &Overloads, - const SourceLocation FinalNoteLoc); /// \brief Conditionally issue a diagnostic based on the current /// evaluation context. diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index c029c584ec..fef52a567f 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -887,14 +887,6 @@ ExprResult Parser::ParseCXXTypeid() { if (RParenLoc.isInvalid()) return ExprError(); - // If we are a foo that identifies a single function, resolve it now... - Expr* e = Result.get(); - if (e->getType() == Actions.Context.OverloadTy) { - ExprResult er = - Actions.ResolveAndFixSingleFunctionTemplateSpecialization(e); - if (er.isUsable()) - Result = er.release(); - } Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/false, Result.release(), RParenLoc); } diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 3f47986367..2cb9275681 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -870,27 +870,40 @@ void PrettyDeclStackTraceEntry::print(raw_ostream &OS) const { /// \param ZeroArgCallReturnTy - If the expression can be turned into a call /// with no arguments, this parameter is set to the type returned by such a /// call; otherwise, it is set to an empty QualType. -/// \param NonTemplateOverloads - If the expression is an overloaded function +/// \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 &NonTemplateOverloads) { + UnresolvedSetImpl &OverloadSet) { ZeroArgCallReturnTy = QualType(); - NonTemplateOverloads.clear(); - if (const OverloadExpr *Overloads = dyn_cast(&E)) { + OverloadSet.clear(); + + if (E.getType() == Context.OverloadTy) { + OverloadExpr::FindResult FR = OverloadExpr::find(const_cast(&E)); + const OverloadExpr *Overloads = FR.Expression; + for (OverloadExpr::decls_iterator it = Overloads->decls_begin(), DeclsEnd = Overloads->decls_end(); it != DeclsEnd; ++it) { - // Our overload set may include TemplateDecls, which we'll ignore for our - // present purpose. - if (const FunctionDecl *OverloadDecl = dyn_cast(*it)) { - NonTemplateOverloads.addDecl(*it); + OverloadSet.addDecl(*it); + + // Check whether the function is a non-template which takes no + // arguments. + if (const FunctionDecl *OverloadDecl + = dyn_cast((*it)->getUnderlyingDecl())) { if (OverloadDecl->getMinRequiredArguments() == 0) ZeroArgCallReturnTy = OverloadDecl->getResultType(); } } + + // Ignore overloads where the address is taken, because apparently + // overload resolution doesn't apply in these cases. In theory, + // this can make us miss a few cases, but whatever. + if (FR.IsAddressOfOperand) + return false; + return true; } - if (const DeclRefExpr *DeclRef = dyn_cast(&E)) { + if (const DeclRefExpr *DeclRef = dyn_cast(E.IgnoreParens())) { if (const FunctionDecl *Fun = dyn_cast(DeclRef->getDecl())) { if (Fun->getMinRequiredArguments() == 0) ZeroArgCallReturnTy = Fun->getResultType(); @@ -937,8 +950,8 @@ bool Sema::isExprCallable(const Expr &E, QualType &ZeroArgCallReturnTy, /// -fshow-overloads=best, this is the location to attach to the note about too /// many candidates. Typically this will be the location of the original /// ill-formed expression. -void Sema::NoteOverloads(const UnresolvedSetImpl &Overloads, - const SourceLocation FinalNoteLoc) { +static void noteOverloads(Sema &S, const UnresolvedSetImpl &Overloads, + const SourceLocation FinalNoteLoc) { int ShownOverloads = 0; int SuppressedOverloads = 0; for (UnresolvedSetImpl::iterator It = Overloads.begin(), @@ -946,15 +959,86 @@ void Sema::NoteOverloads(const UnresolvedSetImpl &Overloads, // FIXME: Magic number for max shown overloads stolen from // OverloadCandidateSet::NoteCandidates. if (ShownOverloads >= 4 && - Diags.getShowOverloads() == DiagnosticsEngine::Ovl_Best) { + S.Diags.getShowOverloads() == DiagnosticsEngine::Ovl_Best) { ++SuppressedOverloads; continue; } - Diag(cast(*It)->getSourceRange().getBegin(), - diag::note_member_ref_possible_intended_overload); + + NamedDecl *Fn = (*It)->getUnderlyingDecl(); + S.Diag(Fn->getLocStart(), diag::note_possible_target_of_call); ++ShownOverloads; } + if (SuppressedOverloads) - Diag(FinalNoteLoc, diag::note_ovl_too_many_candidates) - << SuppressedOverloads; + S.Diag(FinalNoteLoc, diag::note_ovl_too_many_candidates) + << SuppressedOverloads; +} + +static void notePlausibleOverloads(Sema &S, SourceLocation Loc, + const UnresolvedSetImpl &Overloads, + bool (*IsPlausibleResult)(QualType)) { + if (!IsPlausibleResult) + return noteOverloads(S, Overloads, Loc); + + UnresolvedSet<2> PlausibleOverloads; + for (OverloadExpr::decls_iterator It = Overloads.begin(), + DeclsEnd = Overloads.end(); It != DeclsEnd; ++It) { + const FunctionDecl *OverloadDecl = cast(*It); + QualType OverloadResultTy = OverloadDecl->getResultType(); + if (IsPlausibleResult(OverloadResultTy)) + PlausibleOverloads.addDecl(It.getDecl()); + } + noteOverloads(S, PlausibleOverloads, Loc); +} + +/// Determine whether the given expression can be called by just +/// putting parentheses after it. Notably, expressions with unary +/// operators can't be because the unary operator will start parsing +/// outside the call. +static bool IsCallableWithAppend(Expr *E) { + E = E->IgnoreImplicit(); + return (!isa(E) && + !isa(E) && + !isa(E) && + !isa(E)); +} + +bool Sema::tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD, + bool ForceComplain, + bool (*IsPlausibleResult)(QualType)) { + SourceLocation Loc = E.get()->getExprLoc(); + SourceRange Range = E.get()->getSourceRange(); + + QualType ZeroArgCallTy; + UnresolvedSet<4> Overloads; + if (isExprCallable(*E.get(), ZeroArgCallTy, Overloads) && + !ZeroArgCallTy.isNull() && + (!IsPlausibleResult || IsPlausibleResult(ZeroArgCallTy))) { + // At this point, we know E is potentially callable with 0 + // arguments and that it returns something of a reasonable type, + // so we can emit a fixit and carry on pretending that E was + // actually a CallExpr. + SourceLocation ParenInsertionLoc = + PP.getLocForEndOfToken(Range.getEnd()); + Diag(Loc, PD) + << /*zero-arg*/ 1 << Range + << (IsCallableWithAppend(E.get()) + ? FixItHint::CreateInsertion(ParenInsertionLoc, "()") + : FixItHint()); + notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult); + + // FIXME: Try this before emitting the fixit, and suppress diagnostics + // while doing so. + E = ActOnCallExpr(0, E.take(), ParenInsertionLoc, + MultiExprArg(*this, 0, 0), + ParenInsertionLoc.getLocWithOffset(1)); + return true; + } + + if (!ForceComplain) return false; + + Diag(Loc, PD) << /*not zero-arg*/ 0 << Range; + notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult); + E = ExprError(); + return true; } diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp index df9ef4f5bc..8bd9351e0b 100644 --- a/lib/Sema/SemaCast.cpp +++ b/lib/Sema/SemaCast.cpp @@ -49,7 +49,7 @@ namespace { : Self(S), SrcExpr(src), DestType(destType), ResultType(destType.getNonLValueExprType(S.Context)), ValueKind(Expr::getValueKindForType(destType)), - Kind(CK_Dependent), IsARCUnbridgedCast(false) { + Kind(CK_Dependent) { if (const BuiltinType *placeholder = src.get()->getType()->getAsPlaceholderType()) { @@ -65,7 +65,6 @@ namespace { QualType ResultType; ExprValueKind ValueKind; CastKind Kind; - bool IsARCUnbridgedCast; BuiltinType::Kind PlaceholderKind; CXXCastPath BasePath; @@ -639,7 +638,7 @@ void CastOperation::CheckDynamicCast() { /// const char *str = "literal"; /// legacy_function(const_cast\(str)); void CastOperation::CheckConstCast() { - if (ValueKind == VK_RValue) { + if (ValueKind == VK_RValue && !isPlaceholder(BuiltinType::Overload)) { SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take()); if (SrcExpr.isInvalid()) // if conversion failed, don't report another error return; @@ -658,7 +657,7 @@ void CastOperation::CheckConstCast() { /// like this: /// char *bytes = reinterpret_cast\(int_ptr); void CastOperation::CheckReinterpretCast() { - if (ValueKind == VK_RValue) { + if (ValueKind == VK_RValue && !isPlaceholder(BuiltinType::Overload)) { SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take()); if (SrcExpr.isInvalid()) // if conversion failed, don't report another error return; @@ -705,20 +704,20 @@ void CastOperation::CheckStaticCast() { Kind = CK_ToVoid; if (claimPlaceholder(BuiltinType::Overload)) { - ExprResult SingleFunctionExpression = - Self.ResolveAndFixSingleFunctionTemplateSpecialization(SrcExpr.get(), + Self.ResolveAndFixSingleFunctionTemplateSpecialization(SrcExpr, false, // Decay Function to ptr true, // Complain OpRange, DestType, diag::err_bad_static_cast_overload); - if (SingleFunctionExpression.isUsable()) - SrcExpr = SingleFunctionExpression; + if (SrcExpr.isInvalid()) + return; } SrcExpr = Self.IgnoredValueConversions(SrcExpr.take()); return; } - if (ValueKind == VK_RValue && !DestType->isRecordType()) { + if (ValueKind == VK_RValue && !DestType->isRecordType() && + !isPlaceholder(BuiltinType::Overload)) { SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take()); if (SrcExpr.isInvalid()) // if conversion failed, don't report another error return; @@ -1458,17 +1457,19 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, // Is the source an overloaded name? (i.e. &foo) // If so, reinterpret_cast can not help us here (13.4, p1, bullet 5) ... if (SrcType == Self.Context.OverloadTy) { - // ... unless foo resolves to an lvalue unambiguously - ExprResult SingleFunctionExpr = - Self.ResolveAndFixSingleFunctionTemplateSpecialization(SrcExpr.get(), + // ... unless foo resolves to an lvalue unambiguously. + // TODO: what if this fails because of DiagnoseUseOfDecl or something + // like it? + ExprResult SingleFunctionExpr = SrcExpr; + if (Self.ResolveAndFixSingleFunctionTemplateSpecialization( + SingleFunctionExpr, Expr::getValueKindForType(DestType) == VK_RValue // Convert Fun to Ptr - ); - if (SingleFunctionExpr.isUsable()) { + ) && SingleFunctionExpr.isUsable()) { SrcExpr = move(SingleFunctionExpr); SrcType = SrcExpr.get()->getType(); - } - else + } else { return TC_NotApplicable; + } } if (const ReferenceType *DestTypeTmp = DestType->getAs()) { @@ -1736,8 +1737,8 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle) { Kind = CK_ToVoid; if (claimPlaceholder(BuiltinType::Overload)) { - SrcExpr = Self.ResolveAndFixSingleFunctionTemplateSpecialization( - SrcExpr.take(), /* Decay Function to ptr */ false, + Self.ResolveAndFixSingleFunctionTemplateSpecialization( + SrcExpr, /* Decay Function to ptr */ false, /* Complain */ true, DestRange, DestType, diag::err_bad_cstyle_cast_overload); if (SrcExpr.isInvalid()) @@ -1757,7 +1758,8 @@ void CastOperation::CheckCXXCStyleCast(bool FunctionalStyle) { return; } - if (ValueKind == VK_RValue && !DestType->isRecordType()) { + if (ValueKind == VK_RValue && !DestType->isRecordType() && + !isPlaceholder(BuiltinType::Overload)) { SrcExpr = Self.DefaultFunctionArrayLvalueConversion(SrcExpr.take()); if (SrcExpr.isInvalid()) return; @@ -1849,7 +1851,9 @@ void CastOperation::CheckCStyleCast() { return; } - checkNonOverloadPlaceholders(); + // We allow overloads in C, but we don't allow them to be resolved + // by anything except calls. + SrcExpr = Self.CheckPlaceholderExpr(SrcExpr.take()); if (SrcExpr.isInvalid()) return; } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 34be5db15b..d0ad5c8bfd 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -289,6 +289,13 @@ SourceRange Sema::getExprRange(Expr *E) const { /// DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4). ExprResult Sema::DefaultFunctionArrayConversion(Expr *E) { + // Handle any placeholder expressions which made it here. + if (E->getType()->isPlaceholderType()) { + ExprResult result = CheckPlaceholderExpr(E); + if (result.isInvalid()) return ExprError(); + E = result.take(); + } + QualType Ty = E->getType(); assert(!Ty.isNull() && "DefaultFunctionArrayConversion - missing type"); @@ -334,6 +341,13 @@ static void CheckForNullPointerDereference(Sema &S, Expr *E) { } ExprResult Sema::DefaultLvalueConversion(Expr *E) { + // Handle any placeholder expressions which made it here. + if (E->getType()->isPlaceholderType()) { + ExprResult result = CheckPlaceholderExpr(E); + if (result.isInvalid()) return ExprError(); + E = result.take(); + } + // C++ [conv.lval]p1: // A glvalue of a non-function, non-array type T can be // converted to a prvalue. @@ -9976,17 +9990,27 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) { QualType type = E->getType(); // Overloaded expressions. - if (type == Context.OverloadTy) - return ResolveAndFixSingleFunctionTemplateSpecialization(E, false, true, - E->getSourceRange(), - QualType(), - diag::err_ovl_unresolvable); + if (type == Context.OverloadTy) { + // Try to resolve a single function template specialization. + // This is obligatory. + ExprResult result = Owned(E); + if (ResolveAndFixSingleFunctionTemplateSpecialization(result, false)) { + return result; + + // If that failed, try to recover with a call. + } else { + tryToRecoverWithCall(result, PDiag(diag::err_ovl_unresolvable), + /*complain*/ true); + return result; + } + } // Bound member functions. if (type == Context.BoundMemberTy) { - Diag(E->getLocStart(), diag::err_invalid_use_of_bound_member_func) - << E->getSourceRange(); - return ExprError(); + ExprResult result = Owned(E); + tryToRecoverWithCall(result, PDiag(diag::err_bound_member_function), + /*complain*/ true); + return result; } // Expressions of unknown type. diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index 0db8cd494e..6a2b76adfe 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -295,6 +295,12 @@ ExprResult Sema::BuildCXXTypeId(QualType TypeInfoType, SourceLocation RParenLoc) { bool isUnevaluatedOperand = true; if (E && !E->isTypeDependent()) { + if (E->getType()->isPlaceholderType()) { + ExprResult result = CheckPlaceholderExpr(E); + if (result.isInvalid()) return ExprError(); + E = result.take(); + } + QualType T = E->getType(); if (const RecordType *RecordT = T->getAs()) { CXXRecordDecl *RecordD = cast(RecordT->getDecl()); diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp index 918d28ff40..26867c21a1 100644 --- a/lib/Sema/SemaExprMember.cpp +++ b/lib/Sema/SemaExprMember.cpp @@ -970,6 +970,15 @@ static bool ShouldTryAgainWithRedefinitionType(Sema &S, ExprResult &base) { return true; } +static bool isRecordType(QualType T) { + return T->isRecordType(); +} +static bool isPointerToRecordType(QualType T) { + if (const PointerType *PT = T->getAs()) + return PT->getPointeeType()->isRecordType(); + return false; +} + /// Look up the given member of the given non-type-dependent /// expression. This can return in one of two ways: /// * If it returns a sentinel null-but-valid result, the caller will @@ -989,6 +998,8 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, // Perform default conversions. BaseExpr = DefaultFunctionArrayConversion(BaseExpr.take()); + if (BaseExpr.isInvalid()) + return ExprError(); if (IsArrow) { BaseExpr = DefaultLvalueConversion(BaseExpr.take()); @@ -1370,50 +1381,15 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, // If the user is trying to apply -> or . to a function name, it's probably // because they forgot parentheses to call that function. - QualType ZeroArgCallTy; - UnresolvedSet<4> Overloads; - if (isExprCallable(*BaseExpr.get(), ZeroArgCallTy, Overloads)) { - if (ZeroArgCallTy.isNull()) { - Diag(BaseExpr.get()->getExprLoc(), diag::err_member_reference_needs_call) - << (Overloads.size() > 1) << 0 << BaseExpr.get()->getSourceRange(); - UnresolvedSet<2> PlausibleOverloads; - for (OverloadExpr::decls_iterator It = Overloads.begin(), - DeclsEnd = Overloads.end(); It != DeclsEnd; ++It) { - const FunctionDecl *OverloadDecl = cast(*It); - QualType OverloadResultTy = OverloadDecl->getResultType(); - if ((!IsArrow && OverloadResultTy->isRecordType()) || - (IsArrow && OverloadResultTy->isPointerType() && - OverloadResultTy->getPointeeType()->isRecordType())) - PlausibleOverloads.addDecl(It.getDecl()); - } - NoteOverloads(PlausibleOverloads, BaseExpr.get()->getExprLoc()); + if (tryToRecoverWithCall(BaseExpr, + PDiag(diag::err_member_reference_needs_call), + /*complain*/ false, + IsArrow ? &isRecordType : &isPointerToRecordType)) { + if (BaseExpr.isInvalid()) return ExprError(); - } - if ((!IsArrow && ZeroArgCallTy->isRecordType()) || - (IsArrow && ZeroArgCallTy->isPointerType() && - ZeroArgCallTy->getPointeeType()->isRecordType())) { - // At this point, we know BaseExpr looks like it's potentially callable - // with 0 arguments, and that it returns something of a reasonable type, - // so we can emit a fixit and carry on pretending that BaseExpr was - // actually a CallExpr. - SourceLocation ParenInsertionLoc = - PP.getLocForEndOfToken(BaseExpr.get()->getLocEnd()); - Diag(BaseExpr.get()->getExprLoc(), diag::err_member_reference_needs_call) - << (Overloads.size() > 1) << 1 << BaseExpr.get()->getSourceRange() - << FixItHint::CreateInsertion(ParenInsertionLoc, "()"); - // FIXME: Try this before emitting the fixit, and suppress diagnostics - // while doing so. - ExprResult NewBase = - ActOnCallExpr(0, BaseExpr.take(), ParenInsertionLoc, - MultiExprArg(*this, 0, 0), - ParenInsertionLoc.getLocWithOffset(1)); - if (NewBase.isInvalid()) - return ExprError(); - BaseExpr = NewBase; - BaseExpr = DefaultFunctionArrayConversion(BaseExpr.take()); - return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS, - ObjCImpDecl, HasTemplateArgs); - } + BaseExpr = DefaultFunctionArrayConversion(BaseExpr.take()); + return LookupMemberExpr(R, BaseExpr, IsArrow, OpLoc, SS, + ObjCImpDecl, HasTemplateArgs); } Diag(MemberLoc, diag::err_typecheck_member_reference_struct_union) diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index c931160f76..f316cfbe8c 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -8119,25 +8119,31 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, -// Resolve and fix an overloaded expression that -// can be resolved because it identifies a single function -// template specialization +// Resolve and fix an overloaded expression that can be resolved +// because it identifies a single function template specialization. +// // Last three arguments should only be supplied if Complain = true -ExprResult Sema::ResolveAndFixSingleFunctionTemplateSpecialization( - Expr *SrcExpr, bool doFunctionPointerConverion, bool complain, - const SourceRange& OpRangeForComplaining, +// +// Return true if it was logically possible to so resolve the +// expression, regardless of whether or not it succeeded. Always +// returns true if 'complain' is set. +bool Sema::ResolveAndFixSingleFunctionTemplateSpecialization( + ExprResult &SrcExpr, bool doFunctionPointerConverion, + bool complain, const SourceRange& OpRangeForComplaining, QualType DestTypeForComplaining, unsigned DiagIDForComplaining) { - assert(SrcExpr->getType() == Context.OverloadTy); + assert(SrcExpr.get()->getType() == Context.OverloadTy); - OverloadExpr::FindResult ovl = OverloadExpr::find(SrcExpr); + OverloadExpr::FindResult ovl = OverloadExpr::find(SrcExpr.get()); DeclAccessPair found; ExprResult SingleFunctionExpression; if (FunctionDecl *fn = ResolveSingleFunctionTemplateSpecialization( ovl.Expression, /*complain*/ false, &found)) { - if (DiagnoseUseOfDecl(fn, SrcExpr->getSourceRange().getBegin())) - return ExprError(); + if (DiagnoseUseOfDecl(fn, SrcExpr.get()->getSourceRange().getBegin())) { + SrcExpr = ExprError(); + return true; + } // It is only correct to resolve to an instance method if we're // resolving a form that's permitted to be a pointer to member. @@ -8146,28 +8152,34 @@ ExprResult Sema::ResolveAndFixSingleFunctionTemplateSpecialization( if (!ovl.HasFormOfMemberPointer && isa(fn) && cast(fn)->isInstance()) { - if (complain) { - Diag(ovl.Expression->getExprLoc(), - diag::err_invalid_use_of_bound_member_func) - << ovl.Expression->getSourceRange(); - // TODO: I believe we only end up here if there's a mix of - // static and non-static candidates (otherwise the expression - // would have 'bound member' type, not 'overload' type). - // Ideally we would note which candidate was chosen and why - // the static candidates were rejected. - } - - return ExprError(); + if (!complain) return false; + + Diag(ovl.Expression->getExprLoc(), + diag::err_bound_member_function) + << 0 << ovl.Expression->getSourceRange(); + + // TODO: I believe we only end up here if there's a mix of + // static and non-static candidates (otherwise the expression + // would have 'bound member' type, not 'overload' type). + // Ideally we would note which candidate was chosen and why + // the static candidates were rejected. + SrcExpr = ExprError(); + return true; } // Fix the expresion to refer to 'fn'. SingleFunctionExpression = - Owned(FixOverloadedFunctionReference(SrcExpr, found, fn)); + Owned(FixOverloadedFunctionReference(SrcExpr.take(), found, fn)); // If desired, do function-to-pointer decay. - if (doFunctionPointerConverion) + if (doFunctionPointerConverion) { SingleFunctionExpression = DefaultFunctionArrayLvalueConversion(SingleFunctionExpression.take()); + if (SingleFunctionExpression.isInvalid()) { + SrcExpr = ExprError(); + return true; + } + } } if (!SingleFunctionExpression.isUsable()) { @@ -8177,12 +8189,17 @@ ExprResult Sema::ResolveAndFixSingleFunctionTemplateSpecialization( << DestTypeForComplaining << OpRangeForComplaining << ovl.Expression->getQualifierLoc().getSourceRange(); - NoteAllOverloadCandidates(SrcExpr); - } - return ExprError(); + NoteAllOverloadCandidates(SrcExpr.get()); + + SrcExpr = ExprError(); + return true; + } + + return false; } - return SingleFunctionExpression; + SrcExpr = SingleFunctionExpression; + return true; } /// \brief Add a single candidate to the overload set. diff --git a/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp b/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp index 30f8c54919..129a4f4e77 100644 --- a/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp +++ b/test/CXX/expr/expr.unary/expr.unary.op/p6.cpp @@ -29,8 +29,8 @@ bool b8 = !S(); //expected-error {{invalid argument type 'S'}} namespace PR8181 { - void f() { } // expected-note{{candidate function}} - void f(char) { } // expected-note{{candidate function}} - bool b = !&f; //expected-error {{cannot resolve overloaded function 'f' from context}} + void f() { } // expected-note{{possible target for call}} + void f(char) { } // expected-note{{possible target for call}} + bool b = !&f; //expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} } diff --git a/test/CXX/over/over.over/p2-resolve-single-template-id.cpp b/test/CXX/over/over.over/p2-resolve-single-template-id.cpp index 544a66d9e3..d2a23ce96d 100644 --- a/test/CXX/over/over.over/p2-resolve-single-template-id.cpp +++ b/test/CXX/over/over.over/p2-resolve-single-template-id.cpp @@ -27,26 +27,26 @@ namespace DontAllowUnresolvedOverloadedExpressionInAnUnusedExpression void one() { } template void oneT() { } - void two() { } //expected-note 2{{candidate}} - void two(int) { } //expected-note 2{{candidate}} - template void twoT() { } //expected-note 2{{candidate}} - template void twoT(T) { } //expected-note 2{{candidate}} + void two() { } // expected-note 2 {{possible target for call}} + void two(int) { } // expected-note 2 {{possible target for call}} + template void twoT() { } // expected-note 2 {{possible target for call}} + template void twoT(T) { } // expected-note 2 {{possible target for call}} void check() { one; // expected-warning {{expression result unused}} - two; // expected-error{{cannot resolve overloaded function 'two' from context}} + two; // expected-error{{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} oneT; // expected-warning {{expression result unused}} - twoT; // expected-error {{cannot resolve overloaded function 'twoT' from context}} + twoT; // expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} } // check the template function case template void check() { one; // expected-warning {{expression result unused}} - two; // expected-error{{cannot resolve overloaded function 'two' from context}} + two; // expected-error{{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} oneT; // expected-warning {{expression result unused}} - twoT; // expected-error {{cannot resolve overloaded function 'twoT' from context}} + twoT; // expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} } @@ -128,8 +128,8 @@ namespace member_pointers { template bool f(T) { return false; } template static bool g(T) { return false; } - template bool h(T) { return false; } - template static bool h(int) { return false; } + template bool h(T) { return false; } // expected-note 3 {{possible target for call}} + template static bool h(int) { return false; } // expected-note 3 {{possible target for call}} }; void test(S s) { @@ -137,8 +137,8 @@ namespace member_pointers { if (S::f) return; // expected-error {{call to non-static member function without an object argument}} if (&S::f) return; if (&S::f) return; - if (s.f) return; // expected-error {{a bound member function may only be called}} - if (s.f) return; // expected-error {{a bound member function may only be called}} + if (s.f) return; // expected-error {{reference to non-static member function must be called}} + if (s.f) return; // expected-error {{reference to non-static member function must be called}} if (&s.f) return; // expected-error {{cannot create a non-constant pointer to member function}} if (&s.f) return; // expected-error {{cannot create a non-constant pointer to member function}} @@ -152,13 +152,13 @@ namespace member_pointers { if (&s.g) return; if (S::h<42>) return; - if (S::h) return; // expected-error {{a bound member function may only be called}} + if (S::h) return; // expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} if (&S::h<42>) return; if (&S::h) return; if (s.h<42>) return; - if (s.h) return; // expected-error {{a bound member function may only be called}} + if (s.h) return; // expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} if (&s.h<42>) return; - if (&s.h) return; // expected-error {{a bound member function may only be called}} + if (&s.h) return; // expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} { bool b = S::f; } // expected-error {{call to non-static member function without an object argument}} { bool b = S::f; } // expected-error {{call to non-static member function without an object argument}} diff --git a/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-nodeduct.cpp b/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-nodeduct.cpp index 1140aaee6c..de3b44f1b5 100644 --- a/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-nodeduct.cpp +++ b/test/CXX/temp/temp.fct.spec/temp.arg.explicit/p3-nodeduct.cpp @@ -29,8 +29,8 @@ struct is_same { int typeof0[is_same<__typeof__(f), void (int)>::value? 1 : -1]; int typeof1[is_same<__typeof__(&f), void (*)(int)>::value? 1 : -1]; -template void g(T); // expected-note{{candidate function}} -template void g(T, T); // expected-note{{candidate function}} +template void g(T); // expected-note{{possible target for call}} +template void g(T, T); // expected-note{{possible target for call}} int typeof2[is_same<__typeof__(g), void (int)>::value? 1 : -1]; // \ - // expected-error{{cannot resolve overloaded function 'g' from context}} + // expected-error{{reference to overloaded function could not be resolved; did you mean to call it?}} diff --git a/test/FixIt/typo-crash.cpp b/test/FixIt/typo-crash.cpp index 8f0c989cce..92d20377e8 100644 --- a/test/FixIt/typo-crash.cpp +++ b/test/FixIt/typo-crash.cpp @@ -4,9 +4,9 @@ // PR10355 template void template_id1() { // expected-note {{'template_id1' declared here}} \ - // expected-note {{candidate function}} + // expected-note {{possible target for call}} template_id2<> t; // expected-error {{no template named 'template_id2'; did you mean 'template_id1'?}} \ // expected-error {{expected ';' after expression}} \ - // expected-error {{cannot resolve overloaded function 'template_id1' from context}} \ + // expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} \ // expected-error {{use of undeclared identifier 't'}} } diff --git a/test/SemaCXX/PR7944.cpp b/test/SemaCXX/PR7944.cpp index a998a15c3e..51b3f6bcce 100644 --- a/test/SemaCXX/PR7944.cpp +++ b/test/SemaCXX/PR7944.cpp @@ -8,5 +8,5 @@ struct A { B* b() { return new B; } }; void g() { A a; - MACRO(a.b->f()); // expected-error{{base of member reference is a function}} + MACRO(a.b->f()); // expected-error{{reference to non-static member function must be called; did you mean to call it with no arguments?}} } diff --git a/test/SemaCXX/alignof-sizeof-reference.cpp b/test/SemaCXX/alignof-sizeof-reference.cpp index 93ba203ae1..1d65abbcc9 100644 --- a/test/SemaCXX/alignof-sizeof-reference.cpp +++ b/test/SemaCXX/alignof-sizeof-reference.cpp @@ -8,14 +8,14 @@ void test() { static_assert(sizeof(r) == 1, "bad size"); } -void f(); // expected-note{{candidate function}} -void f(int); // expected-note{{candidate function}} +void f(); // expected-note{{possible target for call}} +void f(int); // expected-note{{possible target for call}} void g() { - sizeof(&f); // expected-error{{cannot resolve overloaded function 'f' from context}} + sizeof(&f); // expected-error{{reference to overloaded function could not be resolved; did you mean to call it?}} } -template void f_template(); // expected-note{{candidate function}} -template void f_template(T*); // expected-note{{candidate function}} +template void f_template(); // expected-note{{possible target for call}} +template void f_template(T*); // expected-note{{possible target for call}} void rdar9659191() { - (void)alignof(f_template); // expected-error{{cannot resolve overloaded function 'f_template' from context}} + (void)alignof(f_template); // expected-error{{reference to overloaded function could not be resolved; did you mean to call it?}} } diff --git a/test/SemaCXX/decltype-overloaded-functions.cpp b/test/SemaCXX/decltype-overloaded-functions.cpp index f4aacd64dd..3268786c31 100644 --- a/test/SemaCXX/decltype-overloaded-functions.cpp +++ b/test/SemaCXX/decltype-overloaded-functions.cpp @@ -1,15 +1,15 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++0x -void f(); // expected-note{{candidate function}} -void f(int); // expected-note{{candidate function}} -decltype(f) a; // expected-error{{cannot resolve overloaded function 'f' from context}} +void f(); // expected-note{{possible target for call}} +void f(int); // expected-note{{possible target for call}} +decltype(f) a; // expected-error{{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} expected-error {{variable has incomplete type 'decltype(f())' (aka 'void')}} template struct S { - decltype(T::f) * f; // expected-error{{cannot resolve overloaded function 'f' from context}} + decltype(T::f) * f; // expected-error{{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} expected-error {{call to non-static member function without an object argument}} }; struct K { - void f(); // expected-note{{candidate function}} - void f(int); // expected-note{{candidate function}} + void f(); // expected-note{{possible target for call}} + void f(int); // expected-note{{possible target for call}} }; S b; // expected-note{{in instantiation of template class 'S' requested here}} diff --git a/test/SemaCXX/expression-traits.cpp b/test/SemaCXX/expression-traits.cpp index 1cb990e09b..32b3ff91e9 100644 --- a/test/SemaCXX/expression-traits.cpp +++ b/test/SemaCXX/expression-traits.cpp @@ -185,8 +185,8 @@ struct Class : BaseClass template struct NestedClassTemplate {}; - template - static int& NestedFuncTemplate() { return variable; } // expected-note{{candidate function}} + template // expected-note{{possible target for call}} + static int& NestedFuncTemplate() { return variable; } template int& NestedMemfunTemplate() { return variable; } @@ -234,13 +234,13 @@ struct Class : BaseClass // doesn't come up in legal pure C++ programs). This language // extension simply rejects them as requiring additional context __is_lvalue_expr(::Class::NestedFuncTemplate); // qualified-id: template \ - // expected-error{{cannot resolve overloaded function 'NestedFuncTemplate' from context}} + // expected-error{{reference to overloaded function could not be resolved; did you mean to call it?}} __is_lvalue_expr(::Class::NestedMemfunTemplate); // qualified-id: template \ - // expected-error{{a bound member function may only be called}} + // expected-error{{reference to non-static member function must be called}} __is_lvalue_expr(::Class::operator+); // operator-function-id: template \ - // expected-error{{a bound member function may only be called}} + // expected-error{{reference to non-static member function must be called}} //ASSERT_RVALUE(::Class::operator*); // operator-function-id: member function } diff --git a/test/SemaCXX/member-expr.cpp b/test/SemaCXX/member-expr.cpp index 981bae7c77..2e3fd73d7f 100644 --- a/test/SemaCXX/member-expr.cpp +++ b/test/SemaCXX/member-expr.cpp @@ -28,7 +28,7 @@ struct B { A *f0(); }; int f0(B *b) { - return b->f0->f0; // expected-error{{perhaps you meant to call it with no arguments}} + return b->f0->f0; // expected-error{{did you mean to call it with no arguments}} } int i; @@ -118,32 +118,32 @@ namespace rdar8231724 { namespace PR9025 { struct S { int x; }; - S fun(); - int fun(int i); + S fun(); // expected-note{{possible target for call}} + int fun(int i); // expected-note{{possible target for call}} int g() { - return fun.x; // expected-error{{base of member reference is an overloaded function; perhaps you meant to call it with no arguments?}} + return fun.x; // expected-error{{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} } - S fun2(); - S fun2(int i); + S fun2(); // expected-note{{possible target for call}} + S fun2(int i); // expected-note{{possible target for call}} int g2() { - return fun2.x; // expected-error{{base of member reference is an overloaded function; perhaps you meant to call it with no arguments?}} + return fun2.x; // expected-error{{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} } - S fun3(int i=0); - int fun3(int i, int j); + S fun3(int i=0); // expected-note{{possible target for call}} + int fun3(int i, int j); // expected-note{{possible target for call}} int g3() { - return fun3.x; // expected-error{{base of member reference is an overloaded function; perhaps you meant to call it with no arguments?}} + return fun3.x; // expected-error{{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} } - template S fun4(); + template S fun4(); // expected-note{{possible target for call}} int g4() { - return fun4.x; // expected-error{{base of member reference is a function; perhaps you meant to call it?}} + return fun4.x; // expected-error{{reference to overloaded function could not be resolved; did you mean to call it?}} } - S fun5(int i); // expected-note{{possibly valid overload here}} - S fun5(float f); // expected-note{{possibly valid overload here}} + S fun5(int i); // expected-note{{possible target for call}} + S fun5(float f); // expected-note{{possible target for call}} int g5() { - return fun5.x; // expected-error{{base of member reference is an overloaded function; perhaps you meant to call it?}} + return fun5.x; // expected-error{{reference to overloaded function could not be resolved; did you mean to call it?}} } } diff --git a/test/SemaCXX/overloaded-name.cpp b/test/SemaCXX/overloaded-name.cpp index 73f12a9027..a5ec51ced2 100644 --- a/test/SemaCXX/overloaded-name.cpp +++ b/test/SemaCXX/overloaded-name.cpp @@ -1,15 +1,15 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -int ovl(int); // expected-note 3{{candidate function}} -float ovl(float); // expected-note 3{{candidate function}} +int ovl(int); // expected-note 3{{possible target for call}} +float ovl(float); // expected-note 3{{possible target for call}} -template T ovl(T); // expected-note 3{{candidate function}} +template T ovl(T); // expected-note 3{{possible target for call}} void test(bool b) { - (void)((void)0, ovl); // expected-error{{cannot resolve overloaded function 'ovl' from context}} + (void)((void)0, ovl); // expected-error{{reference to overloaded function could not be resolved; did you mean to call it?}} // PR7863 - (void)(b? ovl : &ovl); // expected-error{{cannot resolve overloaded function 'ovl' from context}} - (void)(b? ovl : &ovl); // expected-error{{cannot resolve overloaded function 'ovl' from context}} + (void)(b? ovl : &ovl); // expected-error{{reference to overloaded function could not be resolved; did you mean to call it?}} + (void)(b? ovl : &ovl); // expected-error{{reference to overloaded function could not be resolved; did you mean to call it?}} (void)(b? ovl : ovl); } @@ -21,10 +21,11 @@ namespace rdar9623945 { public: const char* text(void); void g(void) { + // FIXME: why 2x? f(text()); - f(text); // expected-error{{a bound member function may only be called}} + f(text); // expected-error 2{{reference to non-static member function must be called; did you mean to call it with no arguments?}} f(text()); - f(text); // expected-error{{a bound member function may only be called}} + f(text); // expected-error 2{{reference to non-static member function must be called; did you mean to call it with no arguments?}} } }; } diff --git a/test/SemaCXX/overloaded-operator.cpp b/test/SemaCXX/overloaded-operator.cpp index 36d95599ff..1e4a3b7514 100644 --- a/test/SemaCXX/overloaded-operator.cpp +++ b/test/SemaCXX/overloaded-operator.cpp @@ -396,7 +396,7 @@ namespace rdar9136502 { }; void f(X x, Y y) { - y << x.i; // expected-error{{a bound member function may only be called}} + y << x.i; // expected-error{{reference to non-static member function must be called}} } } diff --git a/test/SemaCXX/ptrtomember.cpp b/test/SemaCXX/ptrtomember.cpp index c3917333a5..b74faa2e24 100644 --- a/test/SemaCXX/ptrtomember.cpp +++ b/test/SemaCXX/ptrtomember.cpp @@ -22,12 +22,12 @@ struct S3 { }; void f3(S3* p, void (S3::*m)()) { - p->*m; // expected-error {{a bound member function may only be called}} - (void)(p->*m); // expected-error {{a bound member function may only be called}} - (void)(void*)(p->*m); // expected-error {{a bound member function may only be called}} - (void)reinterpret_cast(p->*m); // expected-error {{a bound member function may only be called}} - if (p->*m) {} // expected-error {{a bound member function may only be called}} - if (!(p->*m)) {} // expected-error {{a bound member function may only be called}} - if (p->m) {}; // expected-error {{a bound member function may only be called}} - if (!p->m) {}; // expected-error {{a bound member function may only be called}} + p->*m; // expected-error {{reference to non-static member function must be called}} + (void)(p->*m); // expected-error {{reference to non-static member function must be called}} + (void)(void*)(p->*m); // expected-error {{reference to non-static member function must be called}} expected-error {{cannot cast from type 'void' to pointer type 'void *'}} + (void)reinterpret_cast(p->*m); // expected-error {{reference to non-static member function must be called}} expected-error {{reinterpret_cast from 'void' to 'void *' is not allowed}} + if (p->*m) {} // expected-error {{reference to non-static member function must be called}} expected-error {{value of type 'void' is not contextually convertible to 'bool'}} + if (!(p->*m)) {} // expected-error {{reference to non-static member function must be called}} expected-error {{invalid argument type 'void' to unary expression}} + if (p->m) {}; // expected-error {{reference to non-static member function must be called}} expected-error {{value of type 'void' is not contextually convertible to 'bool'}} + if (!p->m) {}; // expected-error {{reference to non-static member function must be called}} expected-error {{invalid argument type 'void' to unary expression}} } diff --git a/test/SemaTemplate/resolve-single-template-id.cpp b/test/SemaTemplate/resolve-single-template-id.cpp index 0c4656a8bc..12f3d4177f 100644 --- a/test/SemaTemplate/resolve-single-template-id.cpp +++ b/test/SemaTemplate/resolve-single-template-id.cpp @@ -5,11 +5,11 @@ namespace std { } void one() { } -void two() { } // expected-note 3{{candidate}} -void two(int) { } // expected-note 3{{candidate}} +void two() { } // expected-note 4{{possible target for call}} +void two(int) { } // expected-note 4{{possible target for call}} -template void twoT() { } // expected-note 5{{candidate}} -template void twoT(int) { } // expected-note 5{{candidate}} +template void twoT() { } // expected-note 5{{possible target for call}} +template void twoT(int) { } // expected-note 5{{possible target for call}} template void oneT() { } template void oneT(U) { } @@ -29,18 +29,18 @@ template struct test { }; int main() { one; // expected-warning {{expression result unused}} - two; // expected-error {{cannot resolve overloaded function 'two' from context}} + two; // expected-error {{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} oneT; // expected-warning {{expression result unused}} - twoT; // expected-error {{cannot resolve overloaded function 'twoT' from context}} + twoT; // expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} typeid(oneT); // expected-warning{{expression result unused}} sizeof(oneT); // expected-warning {{expression result unused}} - sizeof(twoT); //expected-error {{cannot resolve overloaded function 'twoT' from context}} + sizeof(twoT); //expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} decltype(oneT)* fun = 0; *one; // expected-warning {{expression result unused}} *oneT; // expected-warning {{expression result unused}} - *two; //expected-error {{cannot resolve overloaded function 'two' from context}} - *twoT; //expected-error {{cannot resolve overloaded function 'twoT' from context}} + *two; //expected-error {{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} expected-error {{indirection requires pointer operand}} + *twoT; //expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} !oneT; // expected-warning {{expression result unused}} +oneT; // expected-warning {{expression result unused}} -oneT; //expected-error {{invalid argument type}} @@ -52,7 +52,7 @@ int main() void (*p1)(int); p1 = oneT; int i = (int) (false ? (void (*)(int))twoT : oneT); //expected-error {{incompatible operand}} - (twoT) == oneT; //expected-error {{cannot resolve overloaded function 'twoT' from context}} + (twoT) == oneT; //expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} {{cannot resolve overloaded function 'twoT' from context}} bool b = oneT; void (*p)() = oneT; test > ti; @@ -66,8 +66,8 @@ int main() oneT < oneT; //expected-warning {{self-comparison always evaluates to false}} \ //expected-warning {{expression result unused}} - two < two; //expected-error {{cannot resolve overloaded function 'two' from context}} - twoT < twoT; //expected-error {{cannot resolve overloaded function 'twoT' from context}} + two < two; //expected-error 2 {{reference to overloaded function could not be resolved; did you mean to call it with no arguments?}} expected-error {{invalid operands to binary expression ('void' and 'void')}} + twoT < twoT; //expected-error {{reference to overloaded function could not be resolved; did you mean to call it?}} {{cannot resolve overloaded function 'twoT' from context}} oneT == 0; // expected-warning {{equality comparison result unused}} \ // expected-note {{use '=' to turn this equality comparison into an assignment}} @@ -78,5 +78,5 @@ struct rdar9108698 { }; void test_rdar9108698(rdar9108698 x) { - x.f; // expected-error{{a bound member function may only be called}} + x.f; // expected-error{{reference to non-static member function must be called}} }