[cfe-commits] r92979 - /cfe/trunk/lib/Sema/SemaOverload.cpp
John McCall
rjmccall at apple.com
Thu Jan 7 16:58:22 PST 2010
Author: rjmccall
Date: Thu Jan 7 18:58:21 2010
New Revision: 92979
URL: http://llvm.org/viewvc/llvm-project?rev=92979&view=rev
Log:
Reorganize PrintOverloadCandidates. No functionality change.
Modified:
cfe/trunk/lib/Sema/SemaOverload.cpp
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=92979&r1=92978&r2=92979&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Thu Jan 7 18:58:21 2010
@@ -4312,6 +4312,127 @@
Diag(Fn->getLocation(), diag::note_ovl_candidate);
}
+namespace {
+
+void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand) {
+ if (Cand->Function->isDeleted() ||
+ Cand->Function->getAttr<UnavailableAttr>()) {
+ // Deleted or "unavailable" function.
+ S.Diag(Cand->Function->getLocation(), diag::note_ovl_candidate_deleted)
+ << Cand->Function->isDeleted();
+ return;
+ } else if (FunctionTemplateDecl *FunTmpl
+ = Cand->Function->getPrimaryTemplate()) {
+ // Function template specialization
+ // FIXME: Give a better reason!
+ S.Diag(Cand->Function->getLocation(), diag::note_ovl_template_candidate)
+ << S.getTemplateArgumentBindingsText(FunTmpl->getTemplateParameters(),
+ *Cand->Function->getTemplateSpecializationArgs());
+ return;
+ }
+
+ // Normal function
+ bool errReported = false;
+ if (!Cand->Viable && Cand->Conversions.size() > 0) {
+ for (int i = Cand->Conversions.size()-1; i >= 0; i--) {
+ const ImplicitConversionSequence &Conversion =
+ Cand->Conversions[i];
+ if ((Conversion.ConversionKind !=
+ ImplicitConversionSequence::BadConversion) ||
+ Conversion.ConversionFunctionSet.size() == 0)
+ continue;
+ S.Diag(Cand->Function->getLocation(),
+ diag::note_ovl_candidate_not_viable) << (i+1);
+ errReported = true;
+ for (int j = Conversion.ConversionFunctionSet.size()-1;
+ j >= 0; j--) {
+ FunctionDecl *Func = Conversion.ConversionFunctionSet[j];
+ S.NoteOverloadCandidate(Func);
+ }
+ }
+ }
+
+ if (!errReported)
+ S.NoteOverloadCandidate(Cand->Function);
+}
+
+void NoteSurrogateCandidate(Sema &S, OverloadCandidate *Cand) {
+ // Desugar the type of the surrogate down to a function type,
+ // retaining as many typedefs as possible while still showing
+ // the function type (and, therefore, its parameter types).
+ QualType FnType = Cand->Surrogate->getConversionType();
+ bool isLValueReference = false;
+ bool isRValueReference = false;
+ bool isPointer = false;
+ if (const LValueReferenceType *FnTypeRef =
+ FnType->getAs<LValueReferenceType>()) {
+ FnType = FnTypeRef->getPointeeType();
+ isLValueReference = true;
+ } else if (const RValueReferenceType *FnTypeRef =
+ FnType->getAs<RValueReferenceType>()) {
+ FnType = FnTypeRef->getPointeeType();
+ isRValueReference = true;
+ }
+ if (const PointerType *FnTypePtr = FnType->getAs<PointerType>()) {
+ FnType = FnTypePtr->getPointeeType();
+ isPointer = true;
+ }
+ // Desugar down to a function type.
+ FnType = QualType(FnType->getAs<FunctionType>(), 0);
+ // Reconstruct the pointer/reference as appropriate.
+ if (isPointer) FnType = S.Context.getPointerType(FnType);
+ if (isRValueReference) FnType = S.Context.getRValueReferenceType(FnType);
+ if (isLValueReference) FnType = S.Context.getLValueReferenceType(FnType);
+
+ S.Diag(Cand->Surrogate->getLocation(), diag::note_ovl_surrogate_cand)
+ << FnType;
+}
+
+void NoteBuiltinOperatorCandidate(Sema &S,
+ const char *Opc,
+ SourceLocation OpLoc,
+ OverloadCandidate *Cand) {
+ assert(Cand->Conversions.size() <= 2 && "builtin operator is not binary");
+ std::string TypeStr("operator");
+ TypeStr += Opc;
+ TypeStr += "(";
+ TypeStr += Cand->BuiltinTypes.ParamTypes[0].getAsString();
+ if (Cand->Conversions.size() == 1) {
+ TypeStr += ")";
+ S.Diag(OpLoc, diag::note_ovl_builtin_unary_candidate) << TypeStr;
+ } else {
+ TypeStr += ", ";
+ TypeStr += Cand->BuiltinTypes.ParamTypes[1].getAsString();
+ TypeStr += ")";
+ S.Diag(OpLoc, diag::note_ovl_builtin_binary_candidate) << TypeStr;
+ }
+}
+
+void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc,
+ OverloadCandidate *Cand) {
+ unsigned NoOperands = Cand->Conversions.size();
+ for (unsigned ArgIdx = 0; ArgIdx < NoOperands; ++ArgIdx) {
+ const ImplicitConversionSequence &ICS = Cand->Conversions[ArgIdx];
+ if (ICS.ConversionKind != ImplicitConversionSequence::BadConversion ||
+ ICS.ConversionFunctionSet.empty())
+ continue;
+ if (CXXConversionDecl *Func = dyn_cast<CXXConversionDecl>(
+ Cand->Conversions[ArgIdx].ConversionFunctionSet[0])) {
+ QualType FromTy =
+ QualType(static_cast<Type*>(ICS.UserDefined.Before.FromTypePtr),0);
+ S.Diag(OpLoc, diag::note_ambiguous_type_conversion)
+ << FromTy << Func->getConversionType();
+ }
+ for (unsigned j = 0; j < ICS.ConversionFunctionSet.size(); j++) {
+ FunctionDecl *Func =
+ Cand->Conversions[ArgIdx].ConversionFunctionSet[j];
+ S.NoteOverloadCandidate(Func);
+ }
+ }
+}
+
+} // 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.
@@ -4320,122 +4441,32 @@
bool OnlyViable,
const char *Opc,
SourceLocation OpLoc) {
+ bool ReportedNonViableOperator = false;
+
OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
LastCand = CandidateSet.end();
- bool Reported = false;
for (; Cand != LastCand; ++Cand) {
- if (Cand->Viable || !OnlyViable) {
- if (Cand->Function) {
- if (Cand->Function->isDeleted() ||
- Cand->Function->getAttr<UnavailableAttr>()) {
- // Deleted or "unavailable" function.
- Diag(Cand->Function->getLocation(), diag::note_ovl_candidate_deleted)
- << Cand->Function->isDeleted();
- } else if (FunctionTemplateDecl *FunTmpl
- = Cand->Function->getPrimaryTemplate()) {
- // Function template specialization
- // FIXME: Give a better reason!
- Diag(Cand->Function->getLocation(), diag::note_ovl_template_candidate)
- << getTemplateArgumentBindingsText(FunTmpl->getTemplateParameters(),
- *Cand->Function->getTemplateSpecializationArgs());
- } else {
- // Normal function
- bool errReported = false;
- if (!Cand->Viable && Cand->Conversions.size() > 0) {
- for (int i = Cand->Conversions.size()-1; i >= 0; i--) {
- const ImplicitConversionSequence &Conversion =
- Cand->Conversions[i];
- if ((Conversion.ConversionKind !=
- ImplicitConversionSequence::BadConversion) ||
- Conversion.ConversionFunctionSet.size() == 0)
- continue;
- Diag(Cand->Function->getLocation(),
- diag::note_ovl_candidate_not_viable) << (i+1);
- errReported = true;
- for (int j = Conversion.ConversionFunctionSet.size()-1;
- j >= 0; j--) {
- FunctionDecl *Func = Conversion.ConversionFunctionSet[j];
- NoteOverloadCandidate(Func);
- }
- }
- }
- if (!errReported)
- NoteOverloadCandidate(Cand->Function);
- }
- } else if (Cand->IsSurrogate) {
- // Desugar the type of the surrogate down to a function type,
- // retaining as many typedefs as possible while still showing
- // the function type (and, therefore, its parameter types).
- QualType FnType = Cand->Surrogate->getConversionType();
- bool isLValueReference = false;
- bool isRValueReference = false;
- bool isPointer = false;
- if (const LValueReferenceType *FnTypeRef =
- FnType->getAs<LValueReferenceType>()) {
- FnType = FnTypeRef->getPointeeType();
- isLValueReference = true;
- } else if (const RValueReferenceType *FnTypeRef =
- FnType->getAs<RValueReferenceType>()) {
- FnType = FnTypeRef->getPointeeType();
- isRValueReference = true;
- }
- if (const PointerType *FnTypePtr = FnType->getAs<PointerType>()) {
- FnType = FnTypePtr->getPointeeType();
- isPointer = true;
- }
- // Desugar down to a function type.
- FnType = QualType(FnType->getAs<FunctionType>(), 0);
- // Reconstruct the pointer/reference as appropriate.
- if (isPointer) FnType = Context.getPointerType(FnType);
- if (isRValueReference) FnType = Context.getRValueReferenceType(FnType);
- if (isLValueReference) FnType = Context.getLValueReferenceType(FnType);
-
- Diag(Cand->Surrogate->getLocation(), diag::note_ovl_surrogate_cand)
- << FnType;
- } else if (OnlyViable) {
- assert(Cand->Conversions.size() <= 2 &&
- "builtin-binary-operator-not-binary");
- std::string TypeStr("operator");
- TypeStr += Opc;
- TypeStr += "(";
- TypeStr += Cand->BuiltinTypes.ParamTypes[0].getAsString();
- if (Cand->Conversions.size() == 1) {
- TypeStr += ")";
- Diag(OpLoc, diag::note_ovl_builtin_unary_candidate) << TypeStr;
- }
- else {
- TypeStr += ", ";
- TypeStr += Cand->BuiltinTypes.ParamTypes[1].getAsString();
- TypeStr += ")";
- Diag(OpLoc, diag::note_ovl_builtin_binary_candidate) << TypeStr;
- }
- }
- else if (!Cand->Viable && !Reported) {
- // Non-viability might be due to ambiguous user-defined conversions,
- // needed for built-in operators. Report them as well, but only once
- // as we have typically many built-in candidates.
- unsigned NoOperands = Cand->Conversions.size();
- for (unsigned ArgIdx = 0; ArgIdx < NoOperands; ++ArgIdx) {
- const ImplicitConversionSequence &ICS = Cand->Conversions[ArgIdx];
- if (ICS.ConversionKind != ImplicitConversionSequence::BadConversion ||
- ICS.ConversionFunctionSet.empty())
- continue;
- if (CXXConversionDecl *Func = dyn_cast<CXXConversionDecl>(
- Cand->Conversions[ArgIdx].ConversionFunctionSet[0])) {
- QualType FromTy =
- QualType(
- static_cast<Type*>(ICS.UserDefined.Before.FromTypePtr),0);
- Diag(OpLoc,diag::note_ambiguous_type_conversion)
- << FromTy << Func->getConversionType();
- }
- for (unsigned j = 0; j < ICS.ConversionFunctionSet.size(); j++) {
- FunctionDecl *Func =
- Cand->Conversions[ArgIdx].ConversionFunctionSet[j];
- NoteOverloadCandidate(Func);
- }
- }
- Reported = true;
- }
+ if (OnlyViable && !Cand->Viable)
+ continue;
+
+ if (Cand->Function)
+ NoteFunctionCandidate(*this, Cand);
+ else if (Cand->IsSurrogate)
+ NoteSurrogateCandidate(*this, Cand);
+
+ // 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)
+ 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) {
+ NoteAmbiguousUserConversions(*this, OpLoc, Cand);
+ ReportedNonViableOperator = true;
}
}
}
More information about the cfe-commits
mailing list