diff options
author | Larisse Voufo <lvoufo@google.com> | 2013-07-19 22:53:23 +0000 |
---|---|---|
committer | Larisse Voufo <lvoufo@google.com> | 2013-07-19 22:53:23 +0000 |
commit | 47c0845e0b388966ae8b9245057b3b2ba89bd589 (patch) | |
tree | 6c375a604eb58a2670b9f936a8c0b2174e8c0606 /clang/lib | |
parent | fa163749c73261867a81fed1226a55a7d2c5b293 (diff) | |
download | bcm5719-llvm-47c0845e0b388966ae8b9245057b3b2ba89bd589.tar.gz bcm5719-llvm-47c0845e0b388966ae8b9245057b3b2ba89bd589.zip |
Revert "Use function overloading instead of template specialization for diagnosis of bad template argument deductions."
This reverts commit a730f548325756d050d4caaa28fcbffdae8dfe95.
llvm-svn: 186729
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 360 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 51 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateDeduction.cpp | 25 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 9 |
4 files changed, 143 insertions, 302 deletions
diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 7ebcd88fe5f..04aaf181af3 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -548,13 +548,13 @@ AmbiguousConversionSequence::copyFrom(const AmbiguousConversionSequence &O) { } namespace { - // Structure used by DeductionFailureInfo to store + // Structure used by OverloadCandidate::DeductionFailureInfo to store // template argument information. struct DFIArguments { TemplateArgument FirstArg; TemplateArgument SecondArg; }; - // Structure used by DeductionFailureInfo to store + // Structure used by OverloadCandidate::DeductionFailureInfo to store // template parameter and template argument information. struct DFIParamWithArguments : DFIArguments { TemplateParameter Param; @@ -563,10 +563,11 @@ namespace { /// \brief Convert from Sema's representation of template deduction information /// to the form used in overload-candidate information. -DeductionFailureInfo MakeDeductionFailureInfo(ASTContext &Context, - Sema::TemplateDeductionResult TDK, - TemplateDeductionInfo &Info) { - DeductionFailureInfo Result; +OverloadCandidate::DeductionFailureInfo +static MakeDeductionFailureInfo(ASTContext &Context, + Sema::TemplateDeductionResult TDK, + TemplateDeductionInfo &Info) { + OverloadCandidate::DeductionFailureInfo Result; Result.Result = static_cast<unsigned>(TDK); Result.HasDiagnostic = false; Result.Data = 0; @@ -624,7 +625,7 @@ DeductionFailureInfo MakeDeductionFailureInfo(ASTContext &Context, return Result; } -void DeductionFailureInfo::Destroy() { +void OverloadCandidate::DeductionFailureInfo::Destroy() { switch (static_cast<Sema::TemplateDeductionResult>(Result)) { case Sema::TDK_Success: case Sema::TDK_Invalid: @@ -658,13 +659,15 @@ void DeductionFailureInfo::Destroy() { } } -PartialDiagnosticAt *DeductionFailureInfo::getSFINAEDiagnostic() { +PartialDiagnosticAt * +OverloadCandidate::DeductionFailureInfo::getSFINAEDiagnostic() { if (HasDiagnostic) return static_cast<PartialDiagnosticAt*>(static_cast<void*>(Diagnostic)); return 0; } -TemplateParameter DeductionFailureInfo::getTemplateParameter() { +TemplateParameter +OverloadCandidate::DeductionFailureInfo::getTemplateParameter() { switch (static_cast<Sema::TemplateDeductionResult>(Result)) { case Sema::TDK_Success: case Sema::TDK_Invalid: @@ -692,7 +695,8 @@ TemplateParameter DeductionFailureInfo::getTemplateParameter() { return TemplateParameter(); } -TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() { +TemplateArgumentList * +OverloadCandidate::DeductionFailureInfo::getTemplateArgumentList() { switch (static_cast<Sema::TemplateDeductionResult>(Result)) { case Sema::TDK_Success: case Sema::TDK_Invalid: @@ -718,7 +722,7 @@ TemplateArgumentList *DeductionFailureInfo::getTemplateArgumentList() { return 0; } -const TemplateArgument *DeductionFailureInfo::getFirstArg() { +const TemplateArgument *OverloadCandidate::DeductionFailureInfo::getFirstArg() { switch (static_cast<Sema::TemplateDeductionResult>(Result)) { case Sema::TDK_Success: case Sema::TDK_Invalid: @@ -744,7 +748,8 @@ const TemplateArgument *DeductionFailureInfo::getFirstArg() { return 0; } -const TemplateArgument *DeductionFailureInfo::getSecondArg() { +const TemplateArgument * +OverloadCandidate::DeductionFailureInfo::getSecondArg() { switch (static_cast<Sema::TemplateDeductionResult>(Result)) { case Sema::TDK_Success: case Sema::TDK_Invalid: @@ -770,7 +775,8 @@ const TemplateArgument *DeductionFailureInfo::getSecondArg() { return 0; } -Expr *DeductionFailureInfo::getExpr() { +Expr * +OverloadCandidate::DeductionFailureInfo::getExpr() { if (static_cast<Sema::TemplateDeductionResult>(Result) == Sema::TDK_FailedOverloadResolution) return static_cast<Expr*>(Data); @@ -8122,7 +8128,7 @@ OverloadCandidateKind ClassifyOverloadCandidate(Sema &S, return isTemplate ? oc_function_template : oc_function; } -void MaybeEmitInheritedConstructorNote(Sema &S, Decl *Fn) { +void MaybeEmitInheritedConstructorNote(Sema &S, FunctionDecl *Fn) { const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(Fn); if (!Ctor) return; @@ -8408,52 +8414,30 @@ void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand, unsigned I) { MaybeEmitInheritedConstructorNote(S, Fn); } -/// Additional arity mismatch diagnosis specific to a function overload -/// candidates. This is not covered by the more general DiagnoseArityMismatch() -/// over a candidate in any candidate set. -bool CheckArityMismatch(Sema &S, OverloadCandidate *Cand, - unsigned NumArgs) { +void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand, + unsigned NumFormalArgs) { + // TODO: treat calls to a missing default constructor as a special case + FunctionDecl *Fn = Cand->Function; + const FunctionProtoType *FnTy = Fn->getType()->getAs<FunctionProtoType>(); + unsigned MinParams = Fn->getMinRequiredArguments(); // With invalid overloaded operators, it's possible that we think we - // have an arity mismatch when in fact it looks like we have the + // have an arity mismatch when it fact it looks like we have the // right number of arguments, because only overloaded operators have // the weird behavior of overloading member and non-member functions. // Just don't report anything. if (Fn->isInvalidDecl() && Fn->getDeclName().getNameKind() == DeclarationName::CXXOperatorName) - return true; - - if (NumArgs < MinParams) { - assert((Cand->FailureKind == ovl_fail_too_few_arguments) || - (Cand->FailureKind == ovl_fail_bad_deduction && - Cand->DeductionFailure.Result == Sema::TDK_TooFewArguments)); - } else { - assert((Cand->FailureKind == ovl_fail_too_many_arguments) || - (Cand->FailureKind == ovl_fail_bad_deduction && - Cand->DeductionFailure.Result == Sema::TDK_TooManyArguments)); - } - - return false; -} - -/// General arity mismatch diagnosis over a candidate in a candidate set. -void DiagnoseArityMismatch(Sema &S, Decl *D, unsigned NumFormalArgs) { - assert(isa<FunctionDecl>(D) && - "The templated declaration should at least be a function" - " when diagnosing bad template argument deduction due to too many" - " or too few arguments"); - - FunctionDecl *Fn = cast<FunctionDecl>(D); - - // TODO: treat calls to a missing default constructor as a special case - const FunctionProtoType *FnTy = Fn->getType()->getAs<FunctionProtoType>(); - unsigned MinParams = Fn->getMinRequiredArguments(); + return; // at least / at most / exactly unsigned mode, modeCount; if (NumFormalArgs < MinParams) { + assert((Cand->FailureKind == ovl_fail_too_few_arguments) || + (Cand->FailureKind == ovl_fail_bad_deduction && + Cand->DeductionFailure.Result == Sema::TDK_TooFewArguments)); if (MinParams != FnTy->getNumArgs() || FnTy->isVariadic() || FnTy->isTemplateVariadic()) mode = 0; // "at least" @@ -8461,6 +8445,9 @@ void DiagnoseArityMismatch(Sema &S, Decl *D, unsigned NumFormalArgs) { mode = 2; // "exactly" modeCount = MinParams; } else { + assert((Cand->FailureKind == ovl_fail_too_many_arguments) || + (Cand->FailureKind == ovl_fail_bad_deduction && + Cand->DeductionFailure.Result == Sema::TDK_TooManyArguments)); if (MinParams != FnTy->getNumArgs()) mode = 1; // "at most" else @@ -8482,42 +8469,25 @@ void DiagnoseArityMismatch(Sema &S, Decl *D, unsigned NumFormalArgs) { MaybeEmitInheritedConstructorNote(S, Fn); } -/// Arity mismatch diagnosis specific to a function overload candidate. -void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand, - unsigned NumFormalArgs) { - if (!CheckArityMismatch(S, Cand, NumFormalArgs)) - DiagnoseArityMismatch(S, Cand->Function, NumFormalArgs); -} - -TemplateDecl *getDescribedTemplate(Decl *Templated) { - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Templated)) - return FD->getDescribedFunctionTemplate(); - else if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(Templated)) - return RD->getDescribedClassTemplate(); - - llvm_unreachable("Unsupported: Getting the described template declaration" - " for bad deduction diagnosis"); -} - /// Diagnose a failed template-argument deduction. -void DiagnoseBadDeduction(Sema &S, Decl *Templated, - DeductionFailureInfo &DeductionFailure, +void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, unsigned NumArgs) { - TemplateParameter Param = DeductionFailure.getTemplateParameter(); + FunctionDecl *Fn = Cand->Function; // pattern + + TemplateParameter Param = Cand->DeductionFailure.getTemplateParameter(); NamedDecl *ParamD; (ParamD = Param.dyn_cast<TemplateTypeParmDecl*>()) || (ParamD = Param.dyn_cast<NonTypeTemplateParmDecl*>()) || (ParamD = Param.dyn_cast<TemplateTemplateParmDecl*>()); - switch (DeductionFailure.Result) { + switch (Cand->DeductionFailure.Result) { case Sema::TDK_Success: llvm_unreachable("TDK_success while diagnosing bad deduction"); case Sema::TDK_Incomplete: { assert(ParamD && "no parameter found for incomplete deduction result"); - S.Diag(Templated->getLocation(), - diag::note_ovl_candidate_incomplete_deduction) - << ParamD->getDeclName(); - MaybeEmitInheritedConstructorNote(S, Templated); + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_incomplete_deduction) + << ParamD->getDeclName(); + MaybeEmitInheritedConstructorNote(S, Fn); return; } @@ -8525,7 +8495,7 @@ void DiagnoseBadDeduction(Sema &S, Decl *Templated, assert(ParamD && "no parameter found for bad qualifiers deduction result"); TemplateTypeParmDecl *TParam = cast<TemplateTypeParmDecl>(ParamD); - QualType Param = DeductionFailure.getFirstArg()->getAsType(); + QualType Param = Cand->DeductionFailure.getFirstArg()->getAsType(); // Param will have been canonicalized, but it should just be a // qualified version of ParamD, so move the qualifiers to that. @@ -8538,11 +8508,11 @@ void DiagnoseBadDeduction(Sema &S, Decl *Templated, // about that. It also doesn't matter as much, because it won't // have any template parameters in it (because deduction isn't // done on dependent types). - QualType Arg = DeductionFailure.getSecondArg()->getAsType(); + QualType Arg = Cand->DeductionFailure.getSecondArg()->getAsType(); - S.Diag(Templated->getLocation(), diag::note_ovl_candidate_underqualified) - << ParamD->getDeclName() << Arg << NonCanonParam; - MaybeEmitInheritedConstructorNote(S, Templated); + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_underqualified) + << ParamD->getDeclName() << Arg << NonCanonParam; + MaybeEmitInheritedConstructorNote(S, Fn); return; } @@ -8557,20 +8527,20 @@ void DiagnoseBadDeduction(Sema &S, Decl *Templated, which = 2; } - S.Diag(Templated->getLocation(), - diag::note_ovl_candidate_inconsistent_deduction) - << which << ParamD->getDeclName() << *DeductionFailure.getFirstArg() - << *DeductionFailure.getSecondArg(); - MaybeEmitInheritedConstructorNote(S, Templated); + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_inconsistent_deduction) + << which << ParamD->getDeclName() + << *Cand->DeductionFailure.getFirstArg() + << *Cand->DeductionFailure.getSecondArg(); + MaybeEmitInheritedConstructorNote(S, Fn); return; } case Sema::TDK_InvalidExplicitArguments: assert(ParamD && "no parameter found for invalid explicit arguments"); if (ParamD->getDeclName()) - S.Diag(Templated->getLocation(), + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_explicit_arg_mismatch_named) - << ParamD->getDeclName(); + << ParamD->getDeclName(); else { int index = 0; if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(ParamD)) @@ -8580,36 +8550,35 @@ void DiagnoseBadDeduction(Sema &S, Decl *Templated, index = NTTP->getIndex(); else index = cast<TemplateTemplateParmDecl>(ParamD)->getIndex(); - S.Diag(Templated->getLocation(), + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_explicit_arg_mismatch_unnamed) - << (index + 1); + << (index + 1); } - MaybeEmitInheritedConstructorNote(S, Templated); + MaybeEmitInheritedConstructorNote(S, Fn); return; case Sema::TDK_TooManyArguments: case Sema::TDK_TooFewArguments: - DiagnoseArityMismatch(S, Templated, NumArgs); + DiagnoseArityMismatch(S, Cand, NumArgs); return; case Sema::TDK_InstantiationDepth: - S.Diag(Templated->getLocation(), - diag::note_ovl_candidate_instantiation_depth); - MaybeEmitInheritedConstructorNote(S, Templated); + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_instantiation_depth); + MaybeEmitInheritedConstructorNote(S, Fn); return; case Sema::TDK_SubstitutionFailure: { // Format the template argument list into the argument string. SmallString<128> TemplateArgString; if (TemplateArgumentList *Args = - DeductionFailure.getTemplateArgumentList()) { + Cand->DeductionFailure.getTemplateArgumentList()) { TemplateArgString = " "; TemplateArgString += S.getTemplateArgumentBindingsText( - getDescribedTemplate(Templated)->getTemplateParameters(), *Args); + Fn->getDescribedFunctionTemplate()->getTemplateParameters(), *Args); } // If this candidate was disabled by enable_if, say so. - PartialDiagnosticAt *PDiag = DeductionFailure.getSFINAEDiagnostic(); + PartialDiagnosticAt *PDiag = Cand->DeductionFailure.getSFINAEDiagnostic(); if (PDiag && PDiag->second.getDiagID() == diag::err_typename_nested_not_found_enable_if) { // FIXME: Use the source range of the condition, and the fully-qualified @@ -8630,25 +8599,25 @@ void DiagnoseBadDeduction(Sema &S, Decl *Templated, PDiag->second.EmitToString(S.getDiagnostics(), SFINAEArgString); } - S.Diag(Templated->getLocation(), - diag::note_ovl_candidate_substitution_failure) - << TemplateArgString << SFINAEArgString << R; - MaybeEmitInheritedConstructorNote(S, Templated); + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_substitution_failure) + << TemplateArgString << SFINAEArgString << R; + MaybeEmitInheritedConstructorNote(S, Fn); return; } case Sema::TDK_FailedOverloadResolution: { - OverloadExpr::FindResult R = OverloadExpr::find(DeductionFailure.getExpr()); - S.Diag(Templated->getLocation(), + OverloadExpr::FindResult R = + OverloadExpr::find(Cand->DeductionFailure.getExpr()); + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_failed_overload_resolution) - << R.Expression->getName(); + << R.Expression->getName(); return; } case Sema::TDK_NonDeducedMismatch: { // FIXME: Provide a source location to indicate what we couldn't match. - TemplateArgument FirstTA = *DeductionFailure.getFirstArg(); - TemplateArgument SecondTA = *DeductionFailure.getSecondArg(); + TemplateArgument FirstTA = *Cand->DeductionFailure.getFirstArg(); + TemplateArgument SecondTA = *Cand->DeductionFailure.getSecondArg(); if (FirstTA.getKind() == TemplateArgument::Template && SecondTA.getKind() == TemplateArgument::Template) { TemplateName FirstTN = FirstTA.getAsTemplate(); @@ -8663,38 +8632,26 @@ void DiagnoseBadDeduction(Sema &S, Decl *Templated, // 2) The diagnostic printer only attempts to find a better // name for types, not decls. // Ideally, this should folded into the diagnostic printer. - S.Diag(Templated->getLocation(), + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_non_deduced_mismatch_qualified) << FirstTN.getAsTemplateDecl() << SecondTN.getAsTemplateDecl(); return; } } } - S.Diag(Templated->getLocation(), - diag::note_ovl_candidate_non_deduced_mismatch) - << FirstTA << SecondTA; + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_non_deduced_mismatch) + << FirstTA << SecondTA; return; } // TODO: diagnose these individually, then kill off // note_ovl_candidate_bad_deduction, which is uselessly vague. case Sema::TDK_MiscellaneousDeductionFailure: - S.Diag(Templated->getLocation(), diag::note_ovl_candidate_bad_deduction); - MaybeEmitInheritedConstructorNote(S, Templated); + S.Diag(Fn->getLocation(), diag::note_ovl_candidate_bad_deduction); + MaybeEmitInheritedConstructorNote(S, Fn); return; } } -/// Diagnose a failed template-argument deduction, for function calls. -void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand, unsigned NumArgs) { - unsigned TDK = Cand->DeductionFailure.Result; - if (TDK == Sema::TDK_TooFewArguments || TDK == Sema::TDK_TooManyArguments) { - if (CheckArityMismatch(S, Cand, NumArgs)) - return; - } - DiagnoseBadDeduction(S, Cand->Function, // pattern - Cand->DeductionFailure, NumArgs); -} - /// CUDA: diagnose an invalid call across targets. void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) { FunctionDecl *Caller = cast<FunctionDecl>(S.CurContext); @@ -8842,7 +8799,7 @@ void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc, } } -static SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) { +SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) { if (Cand->Function) return Cand->Function->getLocation(); if (Cand->IsSurrogate) @@ -8850,7 +8807,8 @@ static SourceLocation GetLocationForCandidate(const OverloadCandidate *Cand) { return SourceLocation(); } -static unsigned RankDeductionFailure(const DeductionFailureInfo &DFI) { +static unsigned +RankDeductionFailure(const OverloadCandidate::DeductionFailureInfo &DFI) { switch ((Sema::TemplateDeductionResult)DFI.Result) { case Sema::TDK_Success: llvm_unreachable("TDK_success while diagnosing bad deduction"); @@ -9143,108 +9101,6 @@ void OverloadCandidateSet::NoteCandidates(Sema &S, S.Diag(OpLoc, diag::note_ovl_too_many_candidates) << int(E - I); } -static SourceLocation -GetLocationForCandidate(const TemplateSpecCandidate *Cand) { - return Cand->Specialization ? Cand->Specialization->getLocation() - : SourceLocation(); -} - -struct CompareTemplateSpecCandidatesForDisplay { - Sema &S; - CompareTemplateSpecCandidatesForDisplay(Sema &S) : S(S) {} - - bool operator()(const TemplateSpecCandidate *L, - const TemplateSpecCandidate *R) { - // Fast-path this check. - if (L == R) - return false; - - // Assuming that both candidates are not matches... - - // Sort by the ranking of deduction failures. - if (L->DeductionFailure.Result != R->DeductionFailure.Result) - return RankDeductionFailure(L->DeductionFailure) < - RankDeductionFailure(R->DeductionFailure); - - // Sort everything else by location. - SourceLocation LLoc = GetLocationForCandidate(L); - SourceLocation RLoc = GetLocationForCandidate(R); - - // Put candidates without locations (e.g. builtins) at the end. - if (LLoc.isInvalid()) - return false; - if (RLoc.isInvalid()) - return true; - - return S.SourceMgr.isBeforeInTranslationUnit(LLoc, RLoc); - } -}; - -/// Diagnose a template argument deduction failure. -/// We are treating these failures as overload failures due to bad -/// deductions. -void TemplateSpecCandidate::NoteDeductionFailure(Sema &S) { - DiagnoseBadDeduction(S, Specialization, // pattern - DeductionFailure, /*NumArgs=*/0); -} - -void TemplateSpecCandidateSet::destroyCandidates() { - for (iterator i = begin(), e = end(); i != e; ++i) { - i->DeductionFailure.Destroy(); - } -} - -void TemplateSpecCandidateSet::clear() { - destroyCandidates(); - Candidates.clear(); -} - -/// NoteCandidates - When no template specialization match is found, prints -/// diagnostic messages containing the non-matching specializations that form -/// the candidate set. -/// This is analoguous to OverloadCandidateSet::NoteCandidates() with -/// OCD == OCD_AllCandidates and Cand->Viable == false. -void TemplateSpecCandidateSet::NoteCandidates(Sema &S, SourceLocation Loc) { - // Sort the candidates by position (assuming no candidate is a match). - // Sorting directly would be prohibitive, so we make a set of pointers - // and sort those. - SmallVector<TemplateSpecCandidate *, 32> Cands; - Cands.reserve(size()); - for (iterator Cand = begin(), LastCand = end(); Cand != LastCand; ++Cand) { - if (Cand->Specialization) - Cands.push_back(Cand); - // Otherwise, this is a non matching builtin candidate. We do not, - // in general, want to list every possible builtin candidate. - } - - std::sort(Cands.begin(), Cands.end(), - CompareTemplateSpecCandidatesForDisplay(S)); - - // FIXME: Perhaps rename OverloadsShown and getShowOverloads() - // for generalization purposes (?). - const OverloadsShown ShowOverloads = S.Diags.getShowOverloads(); - - SmallVectorImpl<TemplateSpecCandidate *>::iterator I, E; - unsigned CandsShown = 0; - for (I = Cands.begin(), E = Cands.end(); I != E; ++I) { - TemplateSpecCandidate *Cand = *I; - - // Set an arbitrary limit on the number of candidates we'll spam - // the user with. FIXME: This limit should depend on details of the - // candidate list. - if (CandsShown >= 4 && ShowOverloads == Ovl_Best) - break; - ++CandsShown; - - assert(Cand->Specialization && - "Non-matching built-in candidates are not added to Cands."); - Cand->NoteDeductionFailure(S); - } - - if (I != E) - S.Diag(Loc, diag::note_ovl_too_many_candidates) << int(E - I); -} - // [PossiblyAFunctionType] --> [Return] // NonFunctionType --> NonFunctionType // R (A) --> R(A) @@ -9287,19 +9143,18 @@ class AddressOfFunctionResolver OverloadExpr *OvlExpr; TemplateArgumentListInfo OvlExplicitTemplateArgs; SmallVector<std::pair<DeclAccessPair, FunctionDecl*>, 4> Matches; - TemplateSpecCandidateSet FailedCandidates; public: - AddressOfFunctionResolver(Sema &S, Expr *SourceExpr, - const QualType &TargetType, bool Complain) - : S(S), SourceExpr(SourceExpr), TargetType(TargetType), - Complain(Complain), Context(S.getASTContext()), - TargetTypeIsNonStaticMemberFunction( - !!TargetType->getAs<MemberPointerType>()), - FoundNonTemplateFunction(false), - OvlExprInfo(OverloadExpr::find(SourceExpr)), - OvlExpr(OvlExprInfo.Expression), - FailedCandidates(OvlExpr->getNameLoc()) { + AddressOfFunctionResolver(Sema &S, Expr* SourceExpr, + const QualType& TargetType, bool Complain) + : S(S), SourceExpr(SourceExpr), TargetType(TargetType), + Complain(Complain), Context(S.getASTContext()), + TargetTypeIsNonStaticMemberFunction( + !!TargetType->getAs<MemberPointerType>()), + FoundNonTemplateFunction(false), + OvlExprInfo(OverloadExpr::find(SourceExpr)), + OvlExpr(OvlExprInfo.Expression) + { ExtractUnqualifiedFunctionTypeFromTargetType(); if (!TargetFunctionType->isFunctionType()) { @@ -9377,16 +9232,13 @@ private: // function template specialization, which is added to the set of // overloaded functions considered. FunctionDecl *Specialization = 0; - TemplateDeductionInfo Info(FailedCandidates.getLocation()); + TemplateDeductionInfo Info(OvlExpr->getNameLoc()); if (Sema::TemplateDeductionResult Result = S.DeduceTemplateArguments(FunctionTemplate, &OvlExplicitTemplateArgs, TargetFunctionType, Specialization, Info, /*InOverloadResolution=*/true)) { - // Make a note of the failed deduction for diagnostics. - FailedCandidates.addCandidate() - .set(FunctionTemplate->getTemplatedDecl(), - MakeDeductionFailureInfo(Context, Result, Info)); + // FIXME: make a note of the failed deduction for diagnostics. (void)Result; return false; } @@ -9491,15 +9343,15 @@ private: for (unsigned I = 0, E = Matches.size(); I != E; ++I) MatchesCopy.addDecl(Matches[I].second, Matches[I].first.getAccess()); - // TODO: It looks like FailedCandidates does not serve much purpose - // here, since the no_viable diagnostic has index 0. - UnresolvedSetIterator Result = S.getMostSpecialized( - MatchesCopy.begin(), MatchesCopy.end(), FailedCandidates, TPOC_Other, 0, - SourceExpr->getLocStart(), S.PDiag(), - S.PDiag(diag::err_addr_ovl_ambiguous) << Matches[0] - .second->getDeclName(), - S.PDiag(diag::note_ovl_candidate) << (unsigned)oc_function_template, - Complain, TargetFunctionType); + UnresolvedSetIterator Result = + S.getMostSpecialized(MatchesCopy.begin(), MatchesCopy.end(), + TPOC_Other, 0, SourceExpr->getLocStart(), + S.PDiag(), + S.PDiag(diag::err_addr_ovl_ambiguous) + << Matches[0].second->getDeclName(), + S.PDiag(diag::note_ovl_candidate) + << (unsigned) oc_function_template, + Complain, TargetFunctionType); if (Result != MatchesCopy.end()) { // Make it the first and only element @@ -9528,7 +9380,6 @@ public: S.Diag(OvlExpr->getLocStart(), diag::err_addr_ovl_no_viable) << OvlExpr->getName() << TargetFunctionType << OvlExpr->getSourceRange(); - FailedCandidates.NoteCandidates(S, OvlExpr->getLocStart()); S.NoteAllOverloadCandidates(OvlExpr, TargetFunctionType); } @@ -9645,7 +9496,6 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, TemplateArgumentListInfo ExplicitTemplateArgs; ovl->getExplicitTemplateArgs().copyInto(ExplicitTemplateArgs); - TemplateSpecCandidateSet FailedCandidates(ovl->getNameLoc()); // Look through all of the overloaded functions, searching for one // whose type matches exactly. @@ -9668,16 +9518,12 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl, // function template specialization, which is added to the set of // overloaded functions considered. FunctionDecl *Specialization = 0; - TemplateDeductionInfo Info(FailedCandidates.getLocation()); + TemplateDeductionInfo Info(ovl->getNameLoc()); if (TemplateDeductionResult Result = DeduceTemplateArguments(FunctionTemplate, &ExplicitTemplateArgs, Specialization, Info, /*InOverloadResolution=*/true)) { - // Make a note of the failed deduction for diagnostics. - // TODO: Actually use the failed-deduction info? - FailedCandidates.addCandidate() - .set(FunctionTemplate->getTemplatedDecl(), - MakeDeductionFailureInfo(Context, Result, Info)); + // FIXME: make a note of the failed deduction for diagnostics. (void)Result; continue; } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 7939c48c64b..6f1ab19f10e 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -5925,13 +5925,13 @@ Sema::CheckDependentFunctionTemplateSpecialization(FunctionDecl *FD, /// /// \param Previous the set of declarations that may be specialized by /// this function specialization. -bool Sema::CheckFunctionTemplateSpecialization( - FunctionDecl *FD, TemplateArgumentListInfo *ExplicitTemplateArgs, - LookupResult &Previous) { +bool +Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD, + TemplateArgumentListInfo *ExplicitTemplateArgs, + LookupResult &Previous) { // The set of function template specializations that could match this // explicit function template specialization. UnresolvedSet<8> Candidates; - TemplateSpecCandidateSet FailedCandidates(FD->getLocation()); DeclContext *FDLookupContext = FD->getDeclContext()->getRedeclContext(); for (LookupResult::iterator I = Previous.begin(), E = Previous.end(); @@ -5969,16 +5969,13 @@ bool Sema::CheckFunctionTemplateSpecialization( // Perform template argument deduction to determine whether we may be // specializing this template. // FIXME: It is somewhat wasteful to build - TemplateDeductionInfo Info(FailedCandidates.getLocation()); + TemplateDeductionInfo Info(FD->getLocation()); FunctionDecl *Specialization = 0; if (TemplateDeductionResult TDK = DeduceTemplateArguments(FunTmpl, ExplicitTemplateArgs, FT, Specialization, Info)) { - // Template argument deduction failed; record why it failed, so + // FIXME: Template argument deduction failed; record why it failed, so // that we can provide nifty diagnostics. - FailedCandidates.addCandidate() - .set(FunTmpl->getTemplatedDecl(), - MakeDeductionFailureInfo(Context, TDK, Info)); (void)TDK; continue; } @@ -5989,14 +5986,14 @@ bool Sema::CheckFunctionTemplateSpecialization( } // Find the most specialized function template. - UnresolvedSetIterator Result = getMostSpecialized( - Candidates.begin(), Candidates.end(), FailedCandidates, TPOC_Other, 0, - FD->getLocation(), - PDiag(diag::err_function_template_spec_no_match) << FD->getDeclName(), - PDiag(diag::err_function_template_spec_ambiguous) - << FD->getDeclName() << (ExplicitTemplateArgs != 0), - PDiag(diag::note_function_template_spec_matched)); - + UnresolvedSetIterator Result + = getMostSpecialized(Candidates.begin(), Candidates.end(), + TPOC_Other, 0, FD->getLocation(), + PDiag(diag::err_function_template_spec_no_match) + << FD->getDeclName(), + PDiag(diag::err_function_template_spec_ambiguous) + << FD->getDeclName() << (ExplicitTemplateArgs != 0), + PDiag(diag::note_function_template_spec_matched)); if (Result == Candidates.end()) return true; @@ -6815,7 +6812,6 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // instantiated from the member definition associated with its class // template. UnresolvedSet<8> Matches; - TemplateSpecCandidateSet FailedCandidates(D.getIdentifierLoc()); for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end(); P != PEnd; ++P) { NamedDecl *Prev = *P; @@ -6835,16 +6831,13 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, if (!FunTmpl) continue; - TemplateDeductionInfo Info(FailedCandidates.getLocation()); + TemplateDeductionInfo Info(D.getIdentifierLoc()); FunctionDecl *Specialization = 0; if (TemplateDeductionResult TDK = DeduceTemplateArguments(FunTmpl, (HasExplicitTemplateArgs ? &TemplateArgs : 0), R, Specialization, Info)) { - // Keep track of almost-matches. - FailedCandidates.addCandidate() - .set(FunTmpl->getTemplatedDecl(), - MakeDeductionFailureInfo(Context, TDK, Info)); + // FIXME: Keep track of almost-matches? (void)TDK; continue; } @@ -6853,12 +6846,12 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, } // Find the most specialized function template specialization. - UnresolvedSetIterator Result = getMostSpecialized( - Matches.begin(), Matches.end(), FailedCandidates, TPOC_Other, 0, - D.getIdentifierLoc(), - PDiag(diag::err_explicit_instantiation_not_known) << Name, - PDiag(diag::err_explicit_instantiation_ambiguous) << Name, - PDiag(diag::note_explicit_instantiation_candidate)); + UnresolvedSetIterator Result + = getMostSpecialized(Matches.begin(), Matches.end(), TPOC_Other, 0, + D.getIdentifierLoc(), + PDiag(diag::err_explicit_instantiation_not_known) << Name, + PDiag(diag::err_explicit_instantiation_ambiguous) << Name, + PDiag(diag::note_explicit_instantiation_candidate)); if (Result == Matches.end()) return true; diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 8d6aaa096df..29ee6dfa994 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -4148,18 +4148,23 @@ static bool isSameTemplate(TemplateDecl *T1, TemplateDecl *T2) { /// /// \returns the most specialized function template specialization, if /// found. Otherwise, returns SpecEnd. -UnresolvedSetIterator Sema::getMostSpecialized( - UnresolvedSetIterator SpecBegin, UnresolvedSetIterator SpecEnd, - TemplateSpecCandidateSet &FailedCandidates, - TemplatePartialOrderingContext TPOC, unsigned NumCallArguments, - SourceLocation Loc, const PartialDiagnostic &NoneDiag, - const PartialDiagnostic &AmbigDiag, const PartialDiagnostic &CandidateDiag, - bool Complain, QualType TargetType) { +/// +/// \todo FIXME: Consider passing in the "also-ran" candidates that failed +/// template argument deduction. +UnresolvedSetIterator +Sema::getMostSpecialized(UnresolvedSetIterator SpecBegin, + UnresolvedSetIterator SpecEnd, + TemplatePartialOrderingContext TPOC, + unsigned NumCallArguments, + SourceLocation Loc, + const PartialDiagnostic &NoneDiag, + const PartialDiagnostic &AmbigDiag, + const PartialDiagnostic &CandidateDiag, + bool Complain, + QualType TargetType) { if (SpecBegin == SpecEnd) { - if (Complain) { + if (Complain) Diag(Loc, NoneDiag); - FailedCandidates.NoteCandidates(*this, Loc); - } return SpecEnd; } diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 7632bba8c9c..3904daa47f1 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -2252,18 +2252,15 @@ Sema::InstantiateClassTemplateSpecialization( SmallVector<MatchResult, 4> Matched; SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs; Template->getPartialSpecializations(PartialSpecs); - TemplateSpecCandidateSet FailedCandidates(PointOfInstantiation); for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I) { ClassTemplatePartialSpecializationDecl *Partial = PartialSpecs[I]; - TemplateDeductionInfo Info(FailedCandidates.getLocation()); + TemplateDeductionInfo Info(PointOfInstantiation); if (TemplateDeductionResult Result = DeduceTemplateArguments(Partial, ClassTemplateSpec->getTemplateArgs(), Info)) { - // Store the failed-deduction information for use in diagnostics, later. - // TODO: Actually use the failed-deduction info? - FailedCandidates.addCandidate() - .set(Partial, MakeDeductionFailureInfo(Context, Result, Info)); + // FIXME: Store the failed-deduction information for use in + // diagnostics, later. (void)Result; } else { Matched.push_back(PartialSpecMatchResult()); |