diff options
-rw-r--r-- | lib/Sema/Sema.h | 16 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 8 | ||||
-rw-r--r-- | lib/Sema/SemaExprCXX.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaInit.cpp | 15 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 116 | ||||
-rw-r--r-- | test/Sema/overloadable.c | 6 | ||||
-rw-r--r-- | test/SemaCXX/attr-unavailable.cpp | 4 | ||||
-rw-r--r-- | test/SemaCXX/rval-references.cpp | 2 |
8 files changed, 114 insertions, 59 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h index 0b6d16c9ad..54dd060fce 100644 --- a/lib/Sema/Sema.h +++ b/lib/Sema/Sema.h @@ -1028,10 +1028,20 @@ public: OverloadingResult BestViableFunction(OverloadCandidateSet& CandidateSet, SourceLocation Loc, OverloadCandidateSet::iterator& Best); + + enum OverloadCandidateDisplayKind { + /// Requests that all candidates be shown. Viable candidates will + /// be printed first. + OCD_AllCandidates, + + /// Requests that only viable candidates be shown. + OCD_ViableCandidates + }; void PrintOverloadCandidates(OverloadCandidateSet& CandidateSet, - bool OnlyViable, - const char *Opc=0, - SourceLocation Loc=SourceLocation()); + OverloadCandidateDisplayKind OCD, + const char *Opc = 0, + SourceLocation Loc = SourceLocation()); + void NoteOverloadCandidate(FunctionDecl *Fn); FunctionDecl *ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType, diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index d3c8de326c..8965199c2f 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -4193,7 +4193,7 @@ Sema::PerformInitializationByConstructor(QualType ClassType, else Diag(Loc, diag::err_ovl_no_viable_function_in_init) << ClassType << Range; - PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false); + PrintOverloadCandidates(CandidateSet, OCD_AllCandidates); return 0; case OR_Ambiguous: @@ -4201,7 +4201,7 @@ Sema::PerformInitializationByConstructor(QualType ClassType, Diag(Loc, diag::err_ovl_ambiguous_init) << InitEntity << Range; else Diag(Loc, diag::err_ovl_ambiguous_init) << ClassType << Range; - PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); + PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates); return 0; case OR_Deleted: @@ -4216,7 +4216,7 @@ Sema::PerformInitializationByConstructor(QualType ClassType, << Best->Function->isDeleted() << RD->getDeclName() << Range; } - PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); + PrintOverloadCandidates(CandidateSet, OCD_AllCandidates); return 0; } @@ -4540,7 +4540,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType, } Diag(DeclLoc, diag::err_ref_init_ambiguous) << DeclType << Init->getType() << Init->getSourceRange(); - PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/true); + PrintOverloadCandidates(CandidateSet, OCD_ViableCandidates); return true; case OR_No_Viable_Function: diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index fa1a62b14a..6407441aa1 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -673,20 +673,20 @@ bool Sema::FindAllocationOverload(SourceLocation StartLoc, SourceRange Range, case OR_No_Viable_Function: Diag(StartLoc, diag::err_ovl_no_viable_function_in_call) << Name << Range; - PrintOverloadCandidates(Candidates, /*OnlyViable=*/false); + PrintOverloadCandidates(Candidates, OCD_AllCandidates); return true; case OR_Ambiguous: Diag(StartLoc, diag::err_ovl_ambiguous_call) << Name << Range; - PrintOverloadCandidates(Candidates, /*OnlyViable=*/true); + PrintOverloadCandidates(Candidates, OCD_ViableCandidates); return true; case OR_Deleted: Diag(StartLoc, diag::err_ovl_deleted_call) << Best->Function->isDeleted() << Name << Range; - PrintOverloadCandidates(Candidates, /*OnlyViable=*/true); + PrintOverloadCandidates(Candidates, OCD_AllCandidates); return true; } assert(false && "Unreachable, bad result from BestViableFunction"); diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index c2a62cbc52..8c45edb21f 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -88,7 +88,7 @@ static bool CheckSingleInitializer(Expr *&Init, QualType DeclType, S.Diag(Init->getSourceRange().getBegin(), diag::err_typecheck_convert_ambiguous) << DeclType << Init->getType() << Init->getSourceRange(); - S.PrintOverloadCandidates(CandidateSet, /*OnlyViable=*/false); + S.PrintOverloadCandidates(CandidateSet, Sema::OCD_AllCandidates); return true; } return false; @@ -3010,14 +3010,14 @@ static Sema::OwningExprResult CopyIfRequiredForEntity(Sema &S, S.Diag(Loc, diag::err_temp_copy_no_viable) << (int)Entity.getKind() << CurInitExpr->getType() << CurInitExpr->getSourceRange(); - S.PrintOverloadCandidates(CandidateSet, false); + S.PrintOverloadCandidates(CandidateSet, Sema::OCD_AllCandidates); return S.ExprError(); case OR_Ambiguous: S.Diag(Loc, diag::err_temp_copy_ambiguous) << (int)Entity.getKind() << CurInitExpr->getType() << CurInitExpr->getSourceRange(); - S.PrintOverloadCandidates(CandidateSet, true); + S.PrintOverloadCandidates(CandidateSet, Sema::OCD_ViableCandidates); return S.ExprError(); case OR_Deleted: @@ -3432,14 +3432,14 @@ bool InitializationSequence::Diagnose(Sema &S, << DestType << Args[0]->getType() << Args[0]->getSourceRange(); - S.PrintOverloadCandidates(FailedCandidateSet, true); + S.PrintOverloadCandidates(FailedCandidateSet, Sema::OCD_ViableCandidates); break; case OR_No_Viable_Function: S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition) << Args[0]->getType() << DestType.getNonReferenceType() << Args[0]->getSourceRange(); - S.PrintOverloadCandidates(FailedCandidateSet, false); + S.PrintOverloadCandidates(FailedCandidateSet, Sema::OCD_AllCandidates); break; case OR_Deleted: { @@ -3541,13 +3541,14 @@ bool InitializationSequence::Diagnose(Sema &S, case OR_Ambiguous: S.Diag(Kind.getLocation(), diag::err_ovl_ambiguous_init) << DestType << ArgsRange; - S.PrintOverloadCandidates(FailedCandidateSet, true); + S.PrintOverloadCandidates(FailedCandidateSet, + Sema::OCD_ViableCandidates); break; case OR_No_Viable_Function: S.Diag(Kind.getLocation(), diag::err_ovl_no_viable_function_in_init) << DestType << ArgsRange; - S.PrintOverloadCandidates(FailedCandidateSet, false); + S.PrintOverloadCandidates(FailedCandidateSet, Sema::OCD_AllCandidates); break; case OR_Deleted: { 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(); } diff --git a/test/Sema/overloadable.c b/test/Sema/overloadable.c index 72d3673c82..ff631ed9c8 100644 --- a/test/Sema/overloadable.c +++ b/test/Sema/overloadable.c @@ -37,9 +37,9 @@ void test_struct(struct X x, struct Y y) { double *f(int) __attribute__((overloadable)); // expected-error{{conflicting types for 'f'}} -double promote(float) __attribute__((__overloadable__)); -double promote(double) __attribute__((__overloadable__)); -long double promote(long double) __attribute__((__overloadable__)); +double promote(float) __attribute__((__overloadable__)); // expected-note {{candidate}} +double promote(double) __attribute__((__overloadable__)); // expected-note {{candidate}} +long double promote(long double) __attribute__((__overloadable__)); // expected-note {{candidate}} void promote() __attribute__((__overloadable__)); // expected-error{{'overloadable' function 'promote' must have a prototype}} void promote(...) __attribute__((__overloadable__, __unavailable__)); // \ diff --git a/test/SemaCXX/attr-unavailable.cpp b/test/SemaCXX/attr-unavailable.cpp index bebd4cb18e..8b381dfe4b 100644 --- a/test/SemaCXX/attr-unavailable.cpp +++ b/test/SemaCXX/attr-unavailable.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -int &foo(int); -double &foo(double); +int &foo(int); // expected-note {{candidate}} +double &foo(double); // expected-note {{candidate}} void foo(...) __attribute__((__unavailable__)); // expected-note {{candidate function}} \ // expected-note{{function has been explicitly marked unavailable here}} diff --git a/test/SemaCXX/rval-references.cpp b/test/SemaCXX/rval-references.cpp index 1cde26352a..2a7fb25c62 100644 --- a/test/SemaCXX/rval-references.cpp +++ b/test/SemaCXX/rval-references.cpp @@ -65,7 +65,7 @@ int&& should_not_warn(int&& i) { // But GCC 4.4 does // Test the return dance. This also tests IsReturnCopyElidable. struct MoveOnly { MoveOnly(); - MoveOnly(const MoveOnly&) = delete; // expected-note {{candidate function}} \ + MoveOnly(const MoveOnly&) = delete; // expected-note {{candidate constructor}} \ // expected-note 3{{explicitly marked deleted here}} MoveOnly(MoveOnly&&); // expected-note {{candidate constructor}} MoveOnly(int&&); // expected-note {{candidate constructor}} |