aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaOverload.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaOverload.cpp')
-rw-r--r--lib/Sema/SemaOverload.cpp116
1 files changed, 80 insertions, 36 deletions
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index dc590ceab4..825dabfbc7 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -1617,7 +1617,7 @@ Sema::DiagnoseMultipleUserDefinedConversion(Expr *From, QualType ToType) {
<< From->getType() << ToType << From->getSourceRange();
else
return false;
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false);
+ PrintOverloadCandidates(CandidateSet, OCD_AllCandidates);
return true;
}
@@ -4314,14 +4314,20 @@ void Sema::NoteOverloadCandidate(FunctionDecl *Fn) {
namespace {
+void NoteDeletedCandidate(Sema &S, OverloadCandidate *Cand) {
+}
+
void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand) {
- if (Cand->Function->isDeleted() ||
- Cand->Function->getAttr<UnavailableAttr>()) {
- // Deleted or "unavailable" function.
+ // Note deleted candidates, but only if they're viable.
+ if (Cand->Viable &&
+ (Cand->Function->isDeleted() ||
+ Cand->Function->hasAttr<UnavailableAttr>())) {
S.Diag(Cand->Function->getLocation(), diag::note_ovl_candidate_deleted)
<< Cand->Function->isDeleted();
return;
- } else if (FunctionTemplateDecl *FunTmpl
+ }
+
+ if (FunctionTemplateDecl *FunTmpl
= Cand->Function->getPrimaryTemplate()) {
// Function template specialization
// FIXME: Give a better reason!
@@ -4431,23 +4437,61 @@ void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc,
}
}
+struct CompareOverloadCandidates {
+ SourceManager &SM;
+ CompareOverloadCandidates(SourceManager &SM) : SM(SM) {}
+
+ bool operator()(const OverloadCandidate *L,
+ const OverloadCandidate *R) {
+ // Order first by viability.
+ if (L->Viable != R->Viable)
+ return L->Viable;
+
+ // Put declared functions first.
+ if (L->Function) {
+ if (!R->Function) return true;
+ return SM.isBeforeInTranslationUnit(L->Function->getLocation(),
+ R->Function->getLocation());
+ } else if (R->Function) return false;
+
+ // Then surrogates.
+ if (L->IsSurrogate) {
+ if (!R->IsSurrogate) return true;
+ return SM.isBeforeInTranslationUnit(L->Surrogate->getLocation(),
+ R->Surrogate->getLocation());
+ } else if (R->IsSurrogate) return false;
+
+ // And builtins just come in a jumble.
+ return false;
+ }
+};
+
} // end anonymous namespace
/// PrintOverloadCandidates - When overload resolution fails, prints
/// diagnostic messages containing the candidates in the candidate
-/// set. If OnlyViable is true, only viable candidates will be printed.
+/// set.
void
Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
- bool OnlyViable,
+ OverloadCandidateDisplayKind OCD,
const char *Opc,
SourceLocation OpLoc) {
+ // Sort the candidates by viability and position. Sorting directly would
+ // be prohibitive, so we make a set of pointers and sort those.
+ llvm::SmallVector<OverloadCandidate*, 32> Cands;
+ if (OCD == OCD_AllCandidates) Cands.reserve(CandidateSet.size());
+ for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
+ LastCand = CandidateSet.end();
+ Cand != LastCand; ++Cand)
+ if (Cand->Viable || OCD == OCD_AllCandidates)
+ Cands.push_back(Cand);
+ std::sort(Cands.begin(), Cands.end(), CompareOverloadCandidates(SourceMgr));
+
bool ReportedNonViableOperator = false;
- OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
- LastCand = CandidateSet.end();
- for (; Cand != LastCand; ++Cand) {
- if (OnlyViable && !Cand->Viable)
- continue;
+ llvm::SmallVectorImpl<OverloadCandidate*>::iterator I, E;
+ for (I = Cands.begin(), E = Cands.end(); I != E; ++I) {
+ OverloadCandidate *Cand = *I;
if (Cand->Function)
NoteFunctionCandidate(*this, Cand);
@@ -4457,14 +4501,13 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
// This a builtin candidate. We do not, in general, want to list
// every possible builtin candidate.
- // If 'OnlyViable' is true, there were viable candidates.
- // This must be one of them because of the header condition. List it.
- else if (OnlyViable)
+ // If this is a viable builtin, print it.
+ else if (Cand->Viable)
NoteBuiltinOperatorCandidate(*this, Opc, OpLoc, Cand);
// Otherwise, non-viability might be due to ambiguous user-defined
// conversions. Report them exactly once.
- else if (!Cand->Viable && !ReportedNonViableOperator) {
+ else if (!ReportedNonViableOperator) {
NoteAmbiguousUserConversions(*this, OpLoc, Cand);
ReportedNonViableOperator = true;
}
@@ -4975,13 +5018,13 @@ Sema::BuildOverloadedCallExpr(Expr *Fn, UnresolvedLookupExpr *ULE,
Diag(Fn->getSourceRange().getBegin(),
diag::err_ovl_no_viable_function_in_call)
<< ULE->getName() << Fn->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false);
+ PrintOverloadCandidates(CandidateSet, OCD_AllCandidates);
break;
case OR_Ambiguous:
Diag(Fn->getSourceRange().getBegin(), diag::err_ovl_ambiguous_call)
<< ULE->getName() << Fn->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
+ PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates);
break;
case OR_Deleted:
@@ -4989,7 +5032,7 @@ Sema::BuildOverloadedCallExpr(Expr *Fn, UnresolvedLookupExpr *ULE,
<< Best->Function->isDeleted()
<< ULE->getName()
<< Fn->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
+ PrintOverloadCandidates(CandidateSet, OCD_AllCandidates);
break;
}
@@ -5144,7 +5187,7 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc,
Diag(OpLoc, diag::err_ovl_ambiguous_oper)
<< UnaryOperator::getOpcodeStr(Opc)
<< Input->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true,
+ PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates,
UnaryOperator::getOpcodeStr(Opc), OpLoc);
return ExprError();
@@ -5153,7 +5196,7 @@ Sema::OwningExprResult Sema::CreateOverloadedUnaryOp(SourceLocation OpLoc,
<< Best->Function->isDeleted()
<< UnaryOperator::getOpcodeStr(Opc)
<< Input->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
+ PrintOverloadCandidates(CandidateSet, OCD_AllCandidates);
return ExprError();
}
@@ -5360,7 +5403,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
assert(Result.isInvalid() &&
"C++ binary operator overloading is missing candidates!");
if (Result.isInvalid())
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false,
+ PrintOverloadCandidates(CandidateSet, OCD_AllCandidates,
BinaryOperator::getOpcodeStr(Opc), OpLoc);
return move(Result);
}
@@ -5369,7 +5412,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
Diag(OpLoc, diag::err_ovl_ambiguous_oper)
<< BinaryOperator::getOpcodeStr(Opc)
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true,
+ PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates,
BinaryOperator::getOpcodeStr(Opc), OpLoc);
return ExprError();
@@ -5378,7 +5421,7 @@ Sema::CreateOverloadedBinOp(SourceLocation OpLoc,
<< Best->Function->isDeleted()
<< BinaryOperator::getOpcodeStr(Opc)
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
+ PrintOverloadCandidates(CandidateSet, OCD_AllCandidates);
return ExprError();
}
@@ -5488,7 +5531,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
Diag(LLoc, diag::err_ovl_no_viable_subscript)
<< Args[0]->getType()
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false,
+ PrintOverloadCandidates(CandidateSet, OCD_AllCandidates,
"[]", LLoc);
return ExprError();
}
@@ -5496,7 +5539,7 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
case OR_Ambiguous:
Diag(LLoc, diag::err_ovl_ambiguous_oper)
<< "[]" << Args[0]->getSourceRange() << Args[1]->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true,
+ PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates,
"[]", LLoc);
return ExprError();
@@ -5504,7 +5547,8 @@ Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
Diag(LLoc, diag::err_ovl_deleted_oper)
<< Best->Function->isDeleted() << "[]"
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
+ PrintOverloadCandidates(CandidateSet, OCD_AllCandidates,
+ "[]", LLoc);
return ExprError();
}
@@ -5588,14 +5632,14 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
Diag(UnresExpr->getMemberLoc(),
diag::err_ovl_no_viable_member_function_in_call)
<< DeclName << MemExprE->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false);
+ PrintOverloadCandidates(CandidateSet, OCD_AllCandidates);
// FIXME: Leaking incoming expressions!
return ExprError();
case OR_Ambiguous:
Diag(UnresExpr->getMemberLoc(), diag::err_ovl_ambiguous_member_call)
<< DeclName << MemExprE->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false);
+ PrintOverloadCandidates(CandidateSet, OCD_AllCandidates);
// FIXME: Leaking incoming expressions!
return ExprError();
@@ -5603,7 +5647,7 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
Diag(UnresExpr->getMemberLoc(), diag::err_ovl_deleted_member_call)
<< Best->Function->isDeleted()
<< DeclName << MemExprE->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false);
+ PrintOverloadCandidates(CandidateSet, OCD_AllCandidates);
// FIXME: Leaking incoming expressions!
return ExprError();
}
@@ -5752,14 +5796,14 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
Diag(Object->getSourceRange().getBegin(),
diag::err_ovl_no_viable_object_call)
<< Object->getType() << Object->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false);
+ PrintOverloadCandidates(CandidateSet, OCD_AllCandidates);
break;
case OR_Ambiguous:
Diag(Object->getSourceRange().getBegin(),
diag::err_ovl_ambiguous_object_call)
<< Object->getType() << Object->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
+ PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates);
break;
case OR_Deleted:
@@ -5767,7 +5811,7 @@ Sema::BuildCallToObjectOfClassType(Scope *S, Expr *Object,
diag::err_ovl_deleted_object_call)
<< Best->Function->isDeleted()
<< Object->getType() << Object->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
+ PrintOverloadCandidates(CandidateSet, OCD_AllCandidates);
break;
}
@@ -5948,20 +5992,20 @@ Sema::BuildOverloadedArrowExpr(Scope *S, ExprArg BaseIn, SourceLocation OpLoc) {
else
Diag(OpLoc, diag::err_ovl_no_viable_oper)
<< "operator->" << Base->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false);
+ PrintOverloadCandidates(CandidateSet, OCD_AllCandidates);
return ExprError();
case OR_Ambiguous:
Diag(OpLoc, diag::err_ovl_ambiguous_oper)
<< "->" << Base->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
+ PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates);
return ExprError();
case OR_Deleted:
Diag(OpLoc, diag::err_ovl_deleted_oper)
<< Best->Function->isDeleted()
<< "->" << Base->getSourceRange();
- PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true);
+ PrintOverloadCandidates(CandidateSet, OCD_AllCandidates);
return ExprError();
}