diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/Sema.cpp | 116 | ||||
-rw-r--r-- | lib/Sema/SemaCast.cpp | 44 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 40 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaExprMember.cpp | 62 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 73 |
6 files changed, 226 insertions, 115 deletions
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<OverloadExpr>(&E)) { + OverloadSet.clear(); + + if (E.getType() == Context.OverloadTy) { + OverloadExpr::FindResult FR = OverloadExpr::find(const_cast<Expr*>(&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<FunctionDecl>(*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<FunctionDecl>((*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<DeclRefExpr>(&E)) { + if (const DeclRefExpr *DeclRef = dyn_cast<DeclRefExpr>(E.IgnoreParens())) { if (const FunctionDecl *Fun = dyn_cast<FunctionDecl>(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<FunctionDecl>(*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<FunctionDecl>(*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<CStyleCastExpr>(E) && + !isa<UnaryOperator>(E) && + !isa<BinaryOperator>(E) && + !isa<CXXOperatorCallExpr>(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\<char*\>(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\<char*\>(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<int> resolves to an lvalue unambiguously - ExprResult SingleFunctionExpr = - Self.ResolveAndFixSingleFunctionTemplateSpecialization(SrcExpr.get(), + // ... unless foo<int> 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<ReferenceType>()) { @@ -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<RecordType>()) { CXXRecordDecl *RecordD = cast<CXXRecordDecl>(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<PointerType>()) + 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<FunctionDecl>(*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<CXXMethodDecl>(fn) && cast<CXXMethodDecl>(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. |