[cfe-commits] r93214 - in /cfe/trunk: lib/Sema/Sema.h lib/Sema/SemaCXXCast.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaInit.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaOverload.h test/SemaCXX/ambig-user-defined-conversions.cpp test/SemaCXX/builtin-ptrtomember-overload-1.cpp test/SemaCXX/conditional-expr.cpp
John McCall
rjmccall at apple.com
Mon Jan 11 16:44:58 PST 2010
Author: rjmccall
Date: Mon Jan 11 18:44:57 2010
New Revision: 93214
URL: http://llvm.org/viewvc/llvm-project?rev=93214&view=rev
Log:
Introduce a specific representation for the ambiguous implicit conversion
sequence. Lots of small relevant changes. Fixes some serious problems with
ambiguous conversions; also possibly improves associated diagnostics.
Modified:
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaCXXCast.cpp
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaExprCXX.cpp
cfe/trunk/lib/Sema/SemaInit.cpp
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/lib/Sema/SemaOverload.h
cfe/trunk/test/SemaCXX/ambig-user-defined-conversions.cpp
cfe/trunk/test/SemaCXX/builtin-ptrtomember-overload-1.cpp
cfe/trunk/test/SemaCXX/conditional-expr.cpp
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=93214&r1=93213&r2=93214&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Mon Jan 11 18:44:57 2010
@@ -1044,6 +1044,9 @@
SourceLocation Loc = SourceLocation());
void NoteOverloadCandidate(FunctionDecl *Fn);
+ void DiagnoseAmbiguousConversion(const ImplicitConversionSequence &ICS,
+ SourceLocation CaretLoc,
+ const PartialDiagnostic &PDiag);
FunctionDecl *ResolveAddressOfOverloadedFunction(Expr *From, QualType ToType,
bool Complain);
Modified: cfe/trunk/lib/Sema/SemaCXXCast.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXCast.cpp?rev=93214&r1=93213&r2=93214&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaCXXCast.cpp (original)
+++ cfe/trunk/lib/Sema/SemaCXXCast.cpp Mon Jan 11 18:44:57 2010
@@ -893,7 +893,7 @@
/*InOverloadResolution=*/false,
/*one of user provided casts*/true);
- if (ICS.ConversionKind == ImplicitConversionSequence::BadConversion)
+ if (ICS.isBad())
return TC_NotApplicable;
// The conversion is possible, so commit to it.
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=93214&r1=93213&r2=93214&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Jan 11 18:44:57 2010
@@ -4389,8 +4389,7 @@
= CompareReferenceRelationship(DeclLoc, T1, T2, DerivedToBase);
// Most paths end in a failed conversion.
- if (ICS)
- ICS->ConversionKind = ImplicitConversionSequence::BadConversion;
+ if (ICS) ICS->setBad();
// C++ [dcl.init.ref]p5:
// A reference to type "cv1 T1" is initialized by an expression
@@ -4428,7 +4427,7 @@
// has a type that is a derived class of the parameter type,
// in which case the implicit conversion sequence is a
// derived-to-base Conversion (13.3.3.1).
- ICS->ConversionKind = ImplicitConversionSequence::StandardConversion;
+ ICS->setStandard();
ICS->Standard.First = ICK_Identity;
ICS->Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity;
ICS->Standard.Third = ICK_Identity;
@@ -4513,7 +4512,7 @@
// conversion or, if the conversion function returns an
// entity of a type that is a derived class of the parameter
// type, a derived-to-base Conversion.
- ICS->ConversionKind = ImplicitConversionSequence::UserDefinedConversion;
+ ICS->setUserDefined();
ICS->UserDefined.Before = Best->Conversions[0].Standard;
ICS->UserDefined.After = Best->FinalConversion;
ICS->UserDefined.ConversionFunction = Best->Function;
@@ -4539,10 +4538,11 @@
case OR_Ambiguous:
if (ICS) {
+ ICS->setAmbiguous();
for (OverloadCandidateSet::iterator Cand = CandidateSet.begin();
Cand != CandidateSet.end(); ++Cand)
if (Cand->Viable)
- ICS->ConversionFunctionSet.push_back(Cand->Function);
+ ICS->Ambiguous.addConversion(Cand->Function);
break;
}
Diag(DeclLoc, diag::err_ref_init_ambiguous) << DeclType << Init->getType()
@@ -4616,7 +4616,7 @@
if (InitLvalue != Expr::LV_Valid && T2->isRecordType() &&
RefRelationship >= Ref_Compatible_With_Added_Qualification) {
if (ICS) {
- ICS->ConversionKind = ImplicitConversionSequence::StandardConversion;
+ ICS->setStandard();
ICS->Standard.First = ICK_Identity;
ICS->Standard.Second = DerivedToBase? ICK_Derived_To_Base : ICK_Identity;
ICS->Standard.Third = ICK_Identity;
@@ -4688,29 +4688,26 @@
/*InOverloadResolution=*/false);
// Of course, that's still a reference binding.
- if (ICS->ConversionKind == ImplicitConversionSequence::StandardConversion) {
+ if (ICS->isStandard()) {
ICS->Standard.ReferenceBinding = true;
ICS->Standard.RRefBinding = isRValRef;
- } else if (ICS->ConversionKind ==
- ImplicitConversionSequence::UserDefinedConversion) {
+ } else if (ICS->isUserDefined()) {
ICS->UserDefined.After.ReferenceBinding = true;
ICS->UserDefined.After.RRefBinding = isRValRef;
}
- return ICS->ConversionKind == ImplicitConversionSequence::BadConversion;
+ return ICS->isBad();
} else {
ImplicitConversionSequence Conversions;
bool badConversion = PerformImplicitConversion(Init, T1, AA_Initializing,
false, false,
Conversions);
if (badConversion) {
- if ((Conversions.ConversionKind ==
- ImplicitConversionSequence::BadConversion)
- && !Conversions.ConversionFunctionSet.empty()) {
+ if (Conversions.isAmbiguous()) {
Diag(DeclLoc,
diag::err_lvalue_to_rvalue_ambig_ref) << Init->getSourceRange();
- for (int j = Conversions.ConversionFunctionSet.size()-1;
+ for (int j = Conversions.Ambiguous.conversions().size()-1;
j >= 0; j--) {
- FunctionDecl *Func = Conversions.ConversionFunctionSet[j];
+ FunctionDecl *Func = Conversions.Ambiguous.conversions()[j];
NoteOverloadCandidate(Func);
}
}
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=93214&r1=93213&r2=93214&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Mon Jan 11 18:44:57 2010
@@ -1075,7 +1075,7 @@
AssignmentAction Action, bool AllowExplicit,
bool Elidable,
ImplicitConversionSequence& ICS) {
- ICS.ConversionKind = ImplicitConversionSequence::BadConversion;
+ ICS.setBad();
if (Elidable && getLangOptions().CPlusPlus0x) {
ICS = TryImplicitConversion(From, ToType,
/*SuppressUserConversions=*/false,
@@ -1083,7 +1083,7 @@
/*ForceRValue=*/true,
/*InOverloadResolution=*/false);
}
- if (ICS.ConversionKind == ImplicitConversionSequence::BadConversion) {
+ if (ICS.isBad()) {
ICS = TryImplicitConversion(From, ToType,
/*SuppressUserConversions=*/false,
AllowExplicit,
@@ -1103,7 +1103,7 @@
Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
const ImplicitConversionSequence &ICS,
AssignmentAction Action, bool IgnoreBaseAccess) {
- switch (ICS.ConversionKind) {
+ switch (ICS.getKind()) {
case ImplicitConversionSequence::StandardConversion:
if (PerformImplicitConversion(From, ToType, ICS.Standard, Action,
IgnoreBaseAccess))
@@ -1157,6 +1157,12 @@
return PerformImplicitConversion(From, ToType, ICS.UserDefined.After,
AA_Converting, IgnoreBaseAccess);
}
+
+ case ImplicitConversionSequence::AmbiguousConversion:
+ DiagnoseAmbiguousConversion(ICS, From->getExprLoc(),
+ PDiag(diag::err_typecheck_ambiguous_condition)
+ << From->getSourceRange());
+ return true;
case ImplicitConversionSequence::EllipsisConversion:
assert(false && "Cannot perform an ellipsis conversion");
@@ -1474,14 +1480,18 @@
/// \brief Get the target type of a standard or user-defined conversion.
static QualType TargetType(const ImplicitConversionSequence &ICS) {
- assert((ICS.ConversionKind ==
- ImplicitConversionSequence::StandardConversion ||
- ICS.ConversionKind ==
- ImplicitConversionSequence::UserDefinedConversion) &&
- "function only valid for standard or user-defined conversions");
- if (ICS.ConversionKind == ImplicitConversionSequence::StandardConversion)
- return QualType::getFromOpaquePtr(ICS.Standard.ToTypePtr);
- return QualType::getFromOpaquePtr(ICS.UserDefined.After.ToTypePtr);
+ switch (ICS.getKind()) {
+ case ImplicitConversionSequence::StandardConversion:
+ return ICS.Standard.getToType();
+ case ImplicitConversionSequence::UserDefinedConversion:
+ return ICS.UserDefined.After.getToType();
+ case ImplicitConversionSequence::AmbiguousConversion:
+ return ICS.Ambiguous.getToType();
+ case ImplicitConversionSequence::EllipsisConversion:
+ case ImplicitConversionSequence::BadConversion:
+ llvm_unreachable("function not valid for ellipsis or bad conversions");
+ }
+ return QualType(); // silence warnings
}
/// \brief Try to convert a type to another according to C++0x 5.16p3.
@@ -1511,19 +1521,16 @@
/*ForceRValue=*/false,
&ICS))
{
- assert((ICS.ConversionKind ==
- ImplicitConversionSequence::StandardConversion ||
- ICS.ConversionKind ==
- ImplicitConversionSequence::UserDefinedConversion) &&
+ assert((ICS.isStandard() || ICS.isUserDefined()) &&
"expected a definite conversion");
bool DirectBinding =
- ICS.ConversionKind == ImplicitConversionSequence::StandardConversion ?
- ICS.Standard.DirectBinding : ICS.UserDefined.After.DirectBinding;
+ ICS.isStandard() ? ICS.Standard.DirectBinding
+ : ICS.UserDefined.After.DirectBinding;
if (DirectBinding)
return false;
}
}
- ICS.ConversionKind = ImplicitConversionSequence::BadConversion;
+ ICS.setBad();
// -- If E2 is an rvalue, or if the conversion above cannot be done:
// -- if E1 and E2 have class type, and the underlying class types are
// the same or one is a base class of the other:
@@ -1619,8 +1626,7 @@
/// handles the reference binding specially.
static bool ConvertForConditional(Sema &Self, Expr *&E,
const ImplicitConversionSequence &ICS) {
- if (ICS.ConversionKind == ImplicitConversionSequence::StandardConversion &&
- ICS.Standard.ReferenceBinding) {
+ if (ICS.isStandard() && ICS.Standard.ReferenceBinding) {
assert(ICS.Standard.DirectBinding &&
"TryClassUnification should never generate indirect ref bindings");
// FIXME: CheckReferenceInit should be able to reuse the ICS instead of
@@ -1632,8 +1638,7 @@
/*AllowExplicit=*/false,
/*ForceRValue=*/false);
}
- if (ICS.ConversionKind == ImplicitConversionSequence::UserDefinedConversion &&
- ICS.UserDefined.After.ReferenceBinding) {
+ if (ICS.isUserDefined() && ICS.UserDefined.After.ReferenceBinding) {
assert(ICS.UserDefined.After.DirectBinding &&
"TryClassUnification should never generate indirect ref bindings");
return Self.CheckReferenceInit(E, Self.Context.getLValueReferenceType(
@@ -1721,10 +1726,8 @@
if (TryClassUnification(*this, RHS, LHS, QuestionLoc, ICSRightToLeft))
return QualType();
- bool HaveL2R = ICSLeftToRight.ConversionKind !=
- ImplicitConversionSequence::BadConversion;
- bool HaveR2L = ICSRightToLeft.ConversionKind !=
- ImplicitConversionSequence::BadConversion;
+ bool HaveL2R = !ICSLeftToRight.isBad();
+ bool HaveR2L = !ICSRightToLeft.isBad();
// If both can be converted, [...] the program is ill-formed.
if (HaveL2R && HaveR2L) {
Diag(QuestionLoc, diag::err_conditional_ambiguous)
@@ -1938,8 +1941,8 @@
/*InOverloadResolution=*/false);
ImplicitConversionSequence E1ToC2, E2ToC2;
- E1ToC2.ConversionKind = ImplicitConversionSequence::BadConversion;
- E2ToC2.ConversionKind = ImplicitConversionSequence::BadConversion;
+ E1ToC2.setBad();
+ E2ToC2.setBad();
if (Context.getCanonicalType(Composite1) !=
Context.getCanonicalType(Composite2)) {
E1ToC2 = TryImplicitConversion(E1, Composite2,
@@ -1954,14 +1957,8 @@
/*InOverloadResolution=*/false);
}
- bool ToC1Viable = E1ToC1.ConversionKind !=
- ImplicitConversionSequence::BadConversion
- && E2ToC1.ConversionKind !=
- ImplicitConversionSequence::BadConversion;
- bool ToC2Viable = E1ToC2.ConversionKind !=
- ImplicitConversionSequence::BadConversion
- && E2ToC2.ConversionKind !=
- ImplicitConversionSequence::BadConversion;
+ bool ToC1Viable = !E1ToC1.isBad() && !E2ToC1.isBad();
+ bool ToC2Viable = !E1ToC2.isBad() && !E2ToC2.isBad();
if (ToC1Viable && !ToC2Viable) {
if (!PerformImplicitConversion(E1, Composite1, E1ToC1, Sema::AA_Converting) &&
!PerformImplicitConversion(E2, Composite1, E2ToC1, Sema::AA_Converting))
Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=93214&r1=93213&r2=93214&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Mon Jan 11 18:44:57 2010
@@ -670,7 +670,7 @@
/*ForceRValue=*/false,
/*InOverloadResolution=*/false);
- if (ICS.ConversionKind != ImplicitConversionSequence::BadConversion) {
+ if (!ICS.isBad()) {
if (SemaRef.PerformImplicitConversion(expr, ElemType, ICS,
Sema::AA_Initializing))
hadError = true;
@@ -2300,6 +2300,11 @@
Sequence);
if (ConvOvlResult == OR_Success)
return;
+ if (ConvOvlResult != OR_No_Viable_Function) {
+ Sequence.SetOverloadFailure(
+ InitializationSequence::FK_ReferenceInitOverloadFailed,
+ ConvOvlResult);
+ }
}
}
@@ -2384,7 +2389,7 @@
/*FIXME:InOverloadResolution=*/false,
/*UserCast=*/Kind.isExplicitCast());
- if (ICS.ConversionKind == ImplicitConversionSequence::BadConversion) {
+ if (ICS.isBad()) {
// FIXME: Use the conversion function set stored in ICS to turn
// this into an overloading ambiguity diagnostic. However, we need
// to keep that set as an OverloadCandidateSet rather than as some
@@ -2685,14 +2690,14 @@
// Perform overload resolution. If it fails, return the failed result.
OverloadCandidateSet::iterator Best;
- if (OverloadingResult Result
+ if (OverloadingResult Result
= S.BestViableFunction(CandidateSet, DeclLoc, Best)) {
Sequence.SetOverloadFailure(
InitializationSequence::FK_UserConversionOverloadFailed,
Result);
return;
}
-
+
FunctionDecl *Function = Best->Function;
if (isa<CXXConstructorDecl>(Function)) {
@@ -2711,7 +2716,7 @@
if (Best->FinalConversion.First || Best->FinalConversion.Second ||
Best->FinalConversion.Third) {
ImplicitConversionSequence ICS;
- ICS.ConversionKind = ImplicitConversionSequence::StandardConversion;
+ ICS.setStandard();
ICS.Standard = Best->FinalConversion;
Sequence.AddConversionSequenceStep(ICS, DestType);
}
@@ -2732,7 +2737,7 @@
/*FIXME:InOverloadResolution=*/false,
/*UserCast=*/Kind.isExplicitCast());
- if (ICS.ConversionKind == ImplicitConversionSequence::BadConversion) {
+ if (ICS.isBad()) {
Sequence.SetFailed(InitializationSequence::FK_ConversionFailed);
return;
}
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=93214&r1=93213&r2=93214&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Mon Jan 11 18:44:57 2010
@@ -145,15 +145,12 @@
/// used as part of the ranking of standard conversion sequences
/// (C++ 13.3.3.2p4).
bool StandardConversionSequence::isPointerConversionToBool() const {
- QualType FromType = QualType::getFromOpaquePtr(FromTypePtr);
- QualType ToType = QualType::getFromOpaquePtr(ToTypePtr);
-
// Note that FromType has not necessarily been transformed by the
// array-to-pointer or function-to-pointer implicit conversions, so
// check for their presence as well as checking whether FromType is
// a pointer.
- if (ToType->isBooleanType() &&
- (FromType->isPointerType() || FromType->isBlockPointerType() ||
+ if (getToType()->isBooleanType() &&
+ (getFromType()->isPointerType() || getFromType()->isBlockPointerType() ||
First == ICK_Array_To_Pointer || First == ICK_Function_To_Pointer))
return true;
@@ -167,8 +164,8 @@
bool
StandardConversionSequence::
isPointerConversionToVoidPointer(ASTContext& Context) const {
- QualType FromType = QualType::getFromOpaquePtr(FromTypePtr);
- QualType ToType = QualType::getFromOpaquePtr(ToTypePtr);
+ QualType FromType = getFromType();
+ QualType ToType = getToType();
// Note that FromType has not necessarily been transformed by the
// array-to-pointer implicit conversion, so check for its presence
@@ -250,6 +247,9 @@
case EllipsisConversion:
fprintf(stderr, "Ellipsis conversion");
break;
+ case AmbiguousConversion:
+ fprintf(stderr, "Ambiguous conversion");
+ break;
case BadConversion:
fprintf(stderr, "Bad conversion");
break;
@@ -258,6 +258,22 @@
fprintf(stderr, "\n");
}
+void AmbiguousConversionSequence::construct() {
+ new (&conversions()) ConversionSet();
+}
+
+void AmbiguousConversionSequence::destruct() {
+ conversions().~ConversionSet();
+}
+
+void
+AmbiguousConversionSequence::copyFrom(const AmbiguousConversionSequence &O) {
+ FromTypePtr = O.FromTypePtr;
+ ToTypePtr = O.ToTypePtr;
+ new (&conversions()) ConversionSet(O.conversions());
+}
+
+
// IsOverload - Determine whether the given New declaration is an
// overload of the declarations in Old. This routine returns false if
// New and Old cannot be overloaded, e.g., if New has the same
@@ -432,14 +448,14 @@
OverloadCandidateSet Conversions;
OverloadingResult UserDefResult = OR_Success;
if (IsStandardConversion(From, ToType, InOverloadResolution, ICS.Standard))
- ICS.ConversionKind = ImplicitConversionSequence::StandardConversion;
+ ICS.setStandard();
else if (getLangOptions().CPlusPlus &&
(UserDefResult = IsUserDefinedConversion(From, ToType,
ICS.UserDefined,
Conversions,
!SuppressUserConversions, AllowExplicit,
ForceRValue, UserCast)) == OR_Success) {
- ICS.ConversionKind = ImplicitConversionSequence::UserDefinedConversion;
+ ICS.setUserDefined();
// C++ [over.ics.user]p4:
// A conversion of an expression of class type to the same class
// type is given Exact Match rank, and a conversion of an
@@ -456,10 +472,10 @@
(FromCanon == ToCanon || IsDerivedFrom(FromCanon, ToCanon))) {
// Turn this into a "standard" conversion sequence, so that it
// gets ranked with standard conversion sequences.
- ICS.ConversionKind = ImplicitConversionSequence::StandardConversion;
+ ICS.setStandard();
ICS.Standard.setAsIdentityConversion();
- ICS.Standard.FromTypePtr = From->getType().getAsOpaquePtr();
- ICS.Standard.ToTypePtr = ToType.getAsOpaquePtr();
+ ICS.Standard.setFromType(From->getType());
+ ICS.Standard.setToType(ToType);
ICS.Standard.CopyConstructor = Constructor;
if (ToCanon != FromCanon)
ICS.Standard.Second = ICK_Derived_To_Base;
@@ -473,17 +489,18 @@
// of a class copy-initialization, or by 13.3.1.4, 13.3.1.5, or
// 13.3.1.6 in all cases, only standard conversion sequences and
// ellipsis conversion sequences are allowed.
- if (SuppressUserConversions &&
- ICS.ConversionKind == ImplicitConversionSequence::UserDefinedConversion)
- ICS.ConversionKind = ImplicitConversionSequence::BadConversion;
+ if (SuppressUserConversions && ICS.isUserDefined())
+ ICS.setBad();
+ } else if (UserDefResult == OR_Ambiguous) {
+ ICS.setAmbiguous();
+ ICS.Ambiguous.setFromType(From->getType());
+ ICS.Ambiguous.setToType(ToType);
+ for (OverloadCandidateSet::iterator Cand = Conversions.begin();
+ Cand != Conversions.end(); ++Cand)
+ if (Cand->Viable)
+ ICS.Ambiguous.addConversion(Cand->Function);
} else {
- ICS.ConversionKind = ImplicitConversionSequence::BadConversion;
- if (UserDefResult == OR_Ambiguous) {
- for (OverloadCandidateSet::iterator Cand = Conversions.begin();
- Cand != Conversions.end(); ++Cand)
- if (Cand->Viable)
- ICS.ConversionFunctionSet.push_back(Cand->Function);
- }
+ ICS.setBad();
}
return ICS;
@@ -524,7 +541,7 @@
SCS.setAsIdentityConversion();
SCS.Deprecated = false;
SCS.IncompatibleObjC = false;
- SCS.FromTypePtr = FromType.getAsOpaquePtr();
+ SCS.setFromType(FromType);
SCS.CopyConstructor = 0;
// There are no standard conversions for class types in C++, so
@@ -573,7 +590,7 @@
// conversion (4.4). (C++ 4.2p2)
SCS.Second = ICK_Identity;
SCS.Third = ICK_Qualification;
- SCS.ToTypePtr = ToType.getAsOpaquePtr();
+ SCS.setToType(ToType);
return true;
}
} else if (FromType->isFunctionType() && argIsLvalue == Expr::LV_Valid) {
@@ -724,7 +741,7 @@
if (CanonFrom != CanonTo)
return false;
- SCS.ToTypePtr = FromType.getAsOpaquePtr();
+ SCS.setToType(FromType);
return true;
}
@@ -1544,8 +1561,7 @@
// the argument of the constructor.
//
QualType ThisType = Constructor->getThisType(Context);
- if (Best->Conversions[0].ConversionKind ==
- ImplicitConversionSequence::EllipsisConversion)
+ if (Best->Conversions[0].isEllipsis())
User.EllipsisConversion = true;
else {
User.Before = Best->Conversions[0].Standard;
@@ -1553,9 +1569,9 @@
}
User.ConversionFunction = Constructor;
User.After.setAsIdentityConversion();
- User.After.FromTypePtr
- = ThisType->getAs<PointerType>()->getPointeeType().getAsOpaquePtr();
- User.After.ToTypePtr = ToType.getAsOpaquePtr();
+ User.After.setFromType(
+ ThisType->getAs<PointerType>()->getPointeeType());
+ User.After.setToType(ToType);
return OR_Success;
} else if (CXXConversionDecl *Conversion
= dyn_cast<CXXConversionDecl>(Best->Function)) {
@@ -1635,18 +1651,28 @@
// conversion sequence than an ellipsis conversion sequence
// (13.3.3.1.3).
//
- if (ICS1.ConversionKind < ICS2.ConversionKind)
- return ImplicitConversionSequence::Better;
- else if (ICS2.ConversionKind < ICS1.ConversionKind)
- return ImplicitConversionSequence::Worse;
+ // C++0x [over.best.ics]p10:
+ // For the purpose of ranking implicit conversion sequences as
+ // described in 13.3.3.2, the ambiguous conversion sequence is
+ // treated as a user-defined sequence that is indistinguishable
+ // from any other user-defined conversion sequence.
+ if (ICS1.getKind() < ICS2.getKind()) {
+ if (!(ICS1.isUserDefined() && ICS2.isAmbiguous()))
+ return ImplicitConversionSequence::Better;
+ } else if (ICS2.getKind() < ICS1.getKind()) {
+ if (!(ICS2.isUserDefined() && ICS1.isAmbiguous()))
+ return ImplicitConversionSequence::Worse;
+ }
+
+ if (ICS1.isAmbiguous() || ICS2.isAmbiguous())
+ return ImplicitConversionSequence::Indistinguishable;
// Two implicit conversion sequences of the same form are
// indistinguishable conversion sequences unless one of the
// following rules apply: (C++ 13.3.3.2p3):
- if (ICS1.ConversionKind == ImplicitConversionSequence::StandardConversion)
+ if (ICS1.isStandard())
return CompareStandardConversionSequences(ICS1.Standard, ICS2.Standard);
- else if (ICS1.ConversionKind ==
- ImplicitConversionSequence::UserDefinedConversion) {
+ else if (ICS1.isUserDefined()) {
// User-defined conversion sequence U1 is a better conversion
// sequence than another user-defined conversion sequence U2 if
// they contain the same user-defined conversion function or
@@ -1739,8 +1765,8 @@
// Both conversion sequences are conversions to void
// pointers. Compare the source types to determine if there's an
// inheritance relationship in their sources.
- QualType FromType1 = QualType::getFromOpaquePtr(SCS1.FromTypePtr);
- QualType FromType2 = QualType::getFromOpaquePtr(SCS2.FromTypePtr);
+ QualType FromType1 = SCS1.getFromType();
+ QualType FromType2 = SCS2.getFromType();
// Adjust the types we're converting from via the array-to-pointer
// conversion, if we need to.
@@ -1796,8 +1822,8 @@
// top-level cv-qualifiers, and the type to which the reference
// initialized by S2 refers is more cv-qualified than the type
// to which the reference initialized by S1 refers.
- QualType T1 = QualType::getFromOpaquePtr(SCS1.ToTypePtr);
- QualType T2 = QualType::getFromOpaquePtr(SCS2.ToTypePtr);
+ QualType T1 = SCS1.getToType();
+ QualType T2 = SCS2.getToType();
T1 = Context.getCanonicalType(T1);
T2 = Context.getCanonicalType(T2);
Qualifiers T1Quals, T2Quals;
@@ -1927,10 +1953,10 @@
ImplicitConversionSequence::CompareKind
Sema::CompareDerivedToBaseConversions(const StandardConversionSequence& SCS1,
const StandardConversionSequence& SCS2) {
- QualType FromType1 = QualType::getFromOpaquePtr(SCS1.FromTypePtr);
- QualType ToType1 = QualType::getFromOpaquePtr(SCS1.ToTypePtr);
- QualType FromType2 = QualType::getFromOpaquePtr(SCS2.FromTypePtr);
- QualType ToType2 = QualType::getFromOpaquePtr(SCS2.ToTypePtr);
+ QualType FromType1 = SCS1.getFromType();
+ QualType ToType1 = SCS1.getToType();
+ QualType FromType2 = SCS2.getFromType();
+ QualType ToType2 = SCS2.getToType();
// Adjust the types we're converting from via the array-to-pointer
// conversion, if we need to.
@@ -2175,7 +2201,7 @@
// to exit early.
ImplicitConversionSequence ICS;
ICS.Standard.setAsIdentityConversion();
- ICS.ConversionKind = ImplicitConversionSequence::BadConversion;
+ ICS.setBad();
// We need to have an object of class type.
if (const PointerType *PT = FromType->getAs<PointerType>())
@@ -2211,9 +2237,9 @@
return ICS;
// Success. Mark this as a reference binding.
- ICS.ConversionKind = ImplicitConversionSequence::StandardConversion;
- ICS.Standard.FromTypePtr = FromType.getAsOpaquePtr();
- ICS.Standard.ToTypePtr = ImplicitParamType.getAsOpaquePtr();
+ ICS.setStandard();
+ ICS.Standard.setFromType(FromType);
+ ICS.Standard.setToType(ImplicitParamType);
ICS.Standard.ReferenceBinding = true;
ICS.Standard.DirectBinding = true;
ICS.Standard.RRefBinding = false;
@@ -2242,7 +2268,7 @@
ImplicitConversionSequence ICS
= TryObjectArgumentInitialization(From->getType(), Method,
Method->getParent());
- if (ICS.ConversionKind == ImplicitConversionSequence::BadConversion)
+ if (ICS.isBad())
return Diag(From->getSourceRange().getBegin(),
diag::err_implicit_object_parameter_init)
<< ImplicitParamRecordType << FromRecordType << From->getSourceRange();
@@ -2274,8 +2300,8 @@
/// of the expression From to bool (C++0x [conv]p3).
bool Sema::PerformContextuallyConvertToBool(Expr *&From) {
ImplicitConversionSequence ICS = TryContextuallyConvertToBool(From);
- if (!PerformImplicitConversion(From, Context.BoolTy, ICS, AA_Converting))
- return false;
+ if (!ICS.isBad())
+ return PerformImplicitConversion(From, Context.BoolTy, ICS, AA_Converting);
if (!DiagnoseMultipleUserDefinedConversion(From, Context.BoolTy))
return Diag(From->getSourceRange().getBegin(),
@@ -2388,35 +2414,15 @@
= TryCopyInitialization(Args[ArgIdx], ParamType,
SuppressUserConversions, ForceRValue,
/*InOverloadResolution=*/true);
- if (Candidate.Conversions[ArgIdx].ConversionKind
- == ImplicitConversionSequence::BadConversion) {
- // 13.3.3.1-p10 If several different sequences of conversions exist that
- // each convert the argument to the parameter type, the implicit conversion
- // sequence associated with the parameter is defined to be the unique conversion
- // sequence designated the ambiguous conversion sequence. For the purpose of
- // ranking implicit conversion sequences as described in 13.3.3.2, the ambiguous
- // conversion sequence is treated as a user-defined sequence that is
- // indistinguishable from any other user-defined conversion sequence
- if (!Candidate.Conversions[ArgIdx].ConversionFunctionSet.empty()) {
- Candidate.Conversions[ArgIdx].ConversionKind =
- ImplicitConversionSequence::UserDefinedConversion;
- // Set the conversion function to one of them. As due to ambiguity,
- // they carry the same weight and is needed for overload resolution
- // later.
- Candidate.Conversions[ArgIdx].UserDefined.ConversionFunction =
- Candidate.Conversions[ArgIdx].ConversionFunctionSet[0];
- }
- else {
- Candidate.Viable = false;
- break;
- }
+ if (Candidate.Conversions[ArgIdx].isBad()) {
+ Candidate.Viable = false;
+ break;
}
} else {
// (C++ 13.3.2p2): For the purposes of overload resolution, any
// argument for which there is no corresponding parameter is
// considered to ""match the ellipsis" (C+ 13.3.3.1.3).
- Candidate.Conversions[ArgIdx].ConversionKind
- = ImplicitConversionSequence::EllipsisConversion;
+ Candidate.Conversions[ArgIdx].setEllipsis();
}
}
}
@@ -2552,8 +2558,7 @@
// parameter.
Candidate.Conversions[0]
= TryObjectArgumentInitialization(ObjectType, Method, ActingContext);
- if (Candidate.Conversions[0].ConversionKind
- == ImplicitConversionSequence::BadConversion) {
+ if (Candidate.Conversions[0].isBad()) {
Candidate.Viable = false;
return;
}
@@ -2572,8 +2577,7 @@
= TryCopyInitialization(Args[ArgIdx], ParamType,
SuppressUserConversions, ForceRValue,
/*InOverloadResolution=*/true);
- if (Candidate.Conversions[ArgIdx + 1].ConversionKind
- == ImplicitConversionSequence::BadConversion) {
+ if (Candidate.Conversions[ArgIdx + 1].isBad()) {
Candidate.Viable = false;
break;
}
@@ -2581,8 +2585,7 @@
// (C++ 13.3.2p2): For the purposes of overload resolution, any
// argument for which there is no corresponding parameter is
// considered to ""match the ellipsis" (C+ 13.3.3.1.3).
- Candidate.Conversions[ArgIdx + 1].ConversionKind
- = ImplicitConversionSequence::EllipsisConversion;
+ Candidate.Conversions[ArgIdx + 1].setEllipsis();
}
}
}
@@ -2706,9 +2709,8 @@
Candidate.IsSurrogate = false;
Candidate.IgnoreObjectArgument = false;
Candidate.FinalConversion.setAsIdentityConversion();
- Candidate.FinalConversion.FromTypePtr
- = Conversion->getConversionType().getAsOpaquePtr();
- Candidate.FinalConversion.ToTypePtr = ToType.getAsOpaquePtr();
+ Candidate.FinalConversion.setFromType(Conversion->getConversionType());
+ Candidate.FinalConversion.setToType(ToType);
// Determine the implicit conversion sequence for the implicit
// object parameter.
@@ -2722,8 +2724,7 @@
// in overload resolution.
if (Candidate.Conversions[0].Standard.Second == ICK_Derived_To_Base)
Candidate.Conversions[0].Standard.Second = ICK_Identity;
- if (Candidate.Conversions[0].ConversionKind
- == ImplicitConversionSequence::BadConversion) {
+ if (Candidate.Conversions[0].isBad()) {
Candidate.Viable = false;
return;
}
@@ -2766,7 +2767,7 @@
/*ForceRValue=*/false,
/*InOverloadResolution=*/false);
- switch (ICS.ConversionKind) {
+ switch (ICS.getKind()) {
case ImplicitConversionSequence::StandardConversion:
Candidate.FinalConversion = ICS.Standard;
break;
@@ -2844,7 +2845,7 @@
// object parameter.
ImplicitConversionSequence ObjectInit
= TryObjectArgumentInitialization(ObjectType, Conversion, ActingContext);
- if (ObjectInit.ConversionKind == ImplicitConversionSequence::BadConversion) {
+ if (ObjectInit.isBad()) {
Candidate.Viable = false;
return;
}
@@ -2852,8 +2853,7 @@
// The first conversion is actually a user-defined conversion whose
// first conversion is ObjectInit's standard conversion (which is
// effectively a reference binding). Record it as such.
- Candidate.Conversions[0].ConversionKind
- = ImplicitConversionSequence::UserDefinedConversion;
+ Candidate.Conversions[0].setUserDefined();
Candidate.Conversions[0].UserDefined.Before = ObjectInit.Standard;
Candidate.Conversions[0].UserDefined.EllipsisConversion = false;
Candidate.Conversions[0].UserDefined.ConversionFunction = Conversion;
@@ -2894,8 +2894,7 @@
/*SuppressUserConversions=*/false,
/*ForceRValue=*/false,
/*InOverloadResolution=*/false);
- if (Candidate.Conversions[ArgIdx + 1].ConversionKind
- == ImplicitConversionSequence::BadConversion) {
+ if (Candidate.Conversions[ArgIdx + 1].isBad()) {
Candidate.Viable = false;
break;
}
@@ -2903,8 +2902,7 @@
// (C++ 13.3.2p2): For the purposes of overload resolution, any
// argument for which there is no corresponding parameter is
// considered to ""match the ellipsis" (C+ 13.3.3.1.3).
- Candidate.Conversions[ArgIdx + 1].ConversionKind
- = ImplicitConversionSequence::EllipsisConversion;
+ Candidate.Conversions[ArgIdx + 1].setEllipsis();
}
}
}
@@ -3038,8 +3036,7 @@
/*ForceRValue=*/false,
/*InOverloadResolution=*/false);
}
- if (Candidate.Conversions[ArgIdx].ConversionKind
- == ImplicitConversionSequence::BadConversion) {
+ if (Candidate.Conversions[ArgIdx].isBad()) {
Candidate.Viable = false;
break;
}
@@ -4304,11 +4301,22 @@
Diag(Fn->getLocation(), diag::note_ovl_candidate);
}
-namespace {
-
-void NoteDeletedCandidate(Sema &S, OverloadCandidate *Cand) {
+/// Diagnoses an ambiguous conversion. The partial diagnostic is the
+/// "lead" diagnostic; it will be given two arguments, the source and
+/// target types of the conversion.
+void Sema::DiagnoseAmbiguousConversion(const ImplicitConversionSequence &ICS,
+ SourceLocation CaretLoc,
+ const PartialDiagnostic &PDiag) {
+ Diag(CaretLoc, PDiag)
+ << ICS.Ambiguous.getFromType() << ICS.Ambiguous.getToType();
+ for (AmbiguousConversionSequence::const_iterator
+ I = ICS.Ambiguous.begin(), E = ICS.Ambiguous.end(); I != E; ++I) {
+ NoteOverloadCandidate(*I);
+ }
}
+namespace {
+
void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand) {
// Note deleted candidates, but only if they're viable.
if (Cand->Viable &&
@@ -4335,18 +4343,13 @@
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)
+
+ if (!Conversion.isAmbiguous())
continue;
- S.Diag(Cand->Function->getLocation(),
- diag::note_ovl_candidate_not_viable) << (i+1);
+
+ S.DiagnoseAmbiguousConversion(Conversion, Cand->Function->getLocation(),
+ PDiag(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);
- }
}
}
@@ -4411,21 +4414,11 @@
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);
- }
+ if (ICS.isBad()) break; // all meaningless after first invalid
+ if (!ICS.isAmbiguous()) continue;
+
+ S.DiagnoseAmbiguousConversion(ICS, OpLoc,
+ PDiag(diag::note_ambiguous_type_conversion));
}
}
@@ -4479,7 +4472,7 @@
Cands.push_back(Cand);
std::sort(Cands.begin(), Cands.end(), CompareOverloadCandidates(SourceMgr));
- bool ReportedNonViableOperator = false;
+ bool ReportedAmbiguousConversions = false;
llvm::SmallVectorImpl<OverloadCandidate*>::iterator I, E;
for (I = Cands.begin(), E = Cands.end(); I != E; ++I) {
@@ -4492,16 +4485,20 @@
// This a builtin candidate. We do not, in general, want to list
// every possible builtin candidate.
+ else if (Cand->Viable) {
+ // Generally we only see ambiguities including viable builtin
+ // operators if overload resolution got screwed up by an
+ // ambiguous user-defined conversion.
+ //
+ // FIXME: It's quite possible for different conversions to see
+ // different ambiguities, though.
+ if (!ReportedAmbiguousConversions) {
+ NoteAmbiguousUserConversions(*this, OpLoc, Cand);
+ ReportedAmbiguousConversions = true;
+ }
- // If this is a viable builtin, print it.
- else if (Cand->Viable)
+ // If this is a viable builtin, print it.
NoteBuiltinOperatorCandidate(*this, Opc, OpLoc, Cand);
-
- // Otherwise, non-viability might be due to ambiguous user-defined
- // conversions. Report them exactly once.
- else if (!ReportedNonViableOperator) {
- NoteAmbiguousUserConversions(*this, OpLoc, Cand);
- ReportedNonViableOperator = true;
}
}
}
@@ -5414,7 +5411,7 @@
<< Args[0]->getSourceRange() << Args[1]->getSourceRange();
PrintOverloadCandidates(CandidateSet, OCD_AllCandidates);
return ExprError();
- }
+ }
// We matched a built-in operator; build it.
return CreateBuiltinBinOp(OpLoc, Opc, Args[0], Args[1]);
Modified: cfe/trunk/lib/Sema/SemaOverload.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.h?rev=93214&r1=93213&r2=93214&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.h (original)
+++ cfe/trunk/lib/Sema/SemaOverload.h Mon Jan 11 18:44:57 2010
@@ -149,6 +149,15 @@
/// conversions.
CXXConstructorDecl *CopyConstructor;
+ void setFromType(QualType T) { FromTypePtr = T.getAsOpaquePtr(); }
+ void setToType(QualType T) { ToTypePtr = T.getAsOpaquePtr(); }
+ QualType getFromType() const {
+ return QualType::getFromOpaquePtr(FromTypePtr);
+ }
+ QualType getToType() const {
+ return QualType::getFromOpaquePtr(ToTypePtr);
+ }
+
void setAsIdentityConversion();
ImplicitConversionRank getRank() const;
bool isPointerConversionToBool() const;
@@ -190,6 +199,48 @@
void DebugPrint() const;
};
+ /// Represents an ambiguous user-defined conversion sequence.
+ struct AmbiguousConversionSequence {
+ typedef llvm::SmallVector<FunctionDecl*, 4> ConversionSet;
+
+ void *FromTypePtr;
+ void *ToTypePtr;
+ char Buffer[sizeof(ConversionSet)];
+
+ QualType getFromType() const {
+ return QualType::getFromOpaquePtr(FromTypePtr);
+ }
+ QualType getToType() const {
+ return QualType::getFromOpaquePtr(ToTypePtr);
+ }
+ void setFromType(QualType T) { FromTypePtr = T.getAsOpaquePtr(); }
+ void setToType(QualType T) { ToTypePtr = T.getAsOpaquePtr(); }
+
+ ConversionSet &conversions() {
+ return *reinterpret_cast<ConversionSet*>(Buffer);
+ }
+
+ const ConversionSet &conversions() const {
+ return *reinterpret_cast<const ConversionSet*>(Buffer);
+ }
+
+ void addConversion(FunctionDecl *D) {
+ conversions().push_back(D);
+ }
+
+ typedef ConversionSet::iterator iterator;
+ iterator begin() { return conversions().begin(); }
+ iterator end() { return conversions().end(); }
+
+ typedef ConversionSet::const_iterator const_iterator;
+ const_iterator begin() const { return conversions().begin(); }
+ const_iterator end() const { return conversions().end(); }
+
+ void construct();
+ void destruct();
+ void copyFrom(const AmbiguousConversionSequence &);
+ };
+
/// ImplicitConversionSequence - Represents an implicit conversion
/// sequence, which may be a standard conversion sequence
/// (C++ 13.3.3.1.1), user-defined conversion sequence (C++ 13.3.3.1.2),
@@ -197,18 +248,26 @@
struct ImplicitConversionSequence {
/// Kind - The kind of implicit conversion sequence. BadConversion
/// specifies that there is no conversion from the source type to
- /// the target type. The enumerator values are ordered such that
- /// better implicit conversions have smaller values.
+ /// the target type. AmbiguousConversion represents the unique
+ /// ambiguous conversion (C++0x [over.best.ics]p10).
enum Kind {
StandardConversion = 0,
UserDefinedConversion,
+ AmbiguousConversion,
EllipsisConversion,
BadConversion
};
+ private:
/// ConversionKind - The kind of implicit conversion sequence.
Kind ConversionKind;
+ void setKind(Kind K) {
+ if (isAmbiguous()) Ambiguous.destruct();
+ ConversionKind = K;
+ }
+
+ public:
union {
/// When ConversionKind == StandardConversion, provides the
/// details of the standard conversion sequence.
@@ -217,12 +276,54 @@
/// When ConversionKind == UserDefinedConversion, provides the
/// details of the user-defined conversion sequence.
UserDefinedConversionSequence UserDefined;
+
+ /// When ConversionKind == AmbiguousConversion, provides the
+ /// details of the ambiguous conversion.
+ AmbiguousConversionSequence Ambiguous;
};
+
+ ImplicitConversionSequence() : ConversionKind(BadConversion) {}
+ ~ImplicitConversionSequence() {
+ if (isAmbiguous()) Ambiguous.destruct();
+ }
+ ImplicitConversionSequence(const ImplicitConversionSequence &Other)
+ : ConversionKind(Other.ConversionKind)
+ {
+ switch (ConversionKind) {
+ case StandardConversion: Standard = Other.Standard; break;
+ case UserDefinedConversion: UserDefined = Other.UserDefined; break;
+ case AmbiguousConversion: Ambiguous.copyFrom(Other.Ambiguous); break;
+ case EllipsisConversion: break;
+ case BadConversion: break;
+ }
+ }
+
+ ImplicitConversionSequence &
+ operator=(const ImplicitConversionSequence &Other) {
+ if (isAmbiguous()) Ambiguous.destruct();
+ new (this) ImplicitConversionSequence(Other);
+ return *this;
+ }
- /// When ConversionKind == BadConversion due to multiple conversion
- /// functions, this will list those functions.
- llvm::SmallVector<FunctionDecl*, 4> ConversionFunctionSet;
-
+ Kind getKind() const { return ConversionKind; }
+ bool isBad() const { return ConversionKind == BadConversion; }
+ bool isStandard() const { return ConversionKind == StandardConversion; }
+ bool isEllipsis() const { return ConversionKind == EllipsisConversion; }
+ bool isAmbiguous() const { return ConversionKind == AmbiguousConversion; }
+ bool isUserDefined() const {
+ return ConversionKind == UserDefinedConversion;
+ }
+
+ void setBad() { setKind(BadConversion); }
+ void setStandard() { setKind(StandardConversion); }
+ void setEllipsis() { setKind(EllipsisConversion); }
+ void setUserDefined() { setKind(UserDefinedConversion); }
+ void setAmbiguous() {
+ if (isAmbiguous()) return;
+ ConversionKind = AmbiguousConversion;
+ Ambiguous.construct();
+ }
+
// The result of a comparison between implicit conversion
// sequences. Use Sema::CompareImplicitConversionSequences to
// actually perform the comparison.
@@ -280,6 +381,16 @@
/// after the call to the overload candidate to convert the result
/// of calling the conversion function to the required type.
StandardConversionSequence FinalConversion;
+
+ /// hasAmbiguousConversion - Returns whether this overload
+ /// candidate requires an ambiguous conversion or not.
+ bool hasAmbiguousConversion() const {
+ for (llvm::SmallVectorImpl<ImplicitConversionSequence>::const_iterator
+ I = Conversions.begin(), E = Conversions.end(); I != E; ++I) {
+ if (I->isAmbiguous()) return true;
+ }
+ return false;
+ }
};
/// OverloadCandidateSet - A set of overload candidates, used in C++
Modified: cfe/trunk/test/SemaCXX/ambig-user-defined-conversions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/ambig-user-defined-conversions.cpp?rev=93214&r1=93213&r2=93214&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/ambig-user-defined-conversions.cpp (original)
+++ cfe/trunk/test/SemaCXX/ambig-user-defined-conversions.cpp Mon Jan 11 18:44:57 2010
@@ -21,6 +21,13 @@
func(b1, f()); // expected-error {{call to 'func' is ambiguous}}
return f(); // expected-error {{conversion from 'struct test0::B' to 'int const' is ambiguous}}
}
+
+ // This used to crash when comparing the two operands.
+ void func2(const char cc); // expected-note {{candidate function}}
+ void func2(const int ci); // expected-note {{candidate function}}
+ void Test2() {
+ func2(b1); // expected-error {{call to 'func2' is ambiguous}}
+ }
}
namespace test1 {
Modified: cfe/trunk/test/SemaCXX/builtin-ptrtomember-overload-1.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/builtin-ptrtomember-overload-1.cpp?rev=93214&r1=93213&r2=93214&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/builtin-ptrtomember-overload-1.cpp (original)
+++ cfe/trunk/test/SemaCXX/builtin-ptrtomember-overload-1.cpp Mon Jan 11 18:44:57 2010
@@ -40,7 +40,7 @@
}
void foo1(C1 c1, int E::* pmf) {
- // FIXME. Error reporting needs much improvement here.
- int i = c1->*pmf; // expected-error {{left hand operand to ->* must be a pointer to class compatible with the right hand operand, but is 'struct C1'}} \
- // expected-note {{because of ambiguity in conversion of 'struct C1' to 'struct E *'}}
+ int i = c1->*pmf; // expected-error {{use of overloaded operator '->*' is ambiguous}} \
+ // expected-note {{because of ambiguity in conversion of 'struct C1' to 'struct E *'}} \
+ // expected-note 4 {{built-in candidate operator}}
}
Modified: cfe/trunk/test/SemaCXX/conditional-expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/conditional-expr.cpp?rev=93214&r1=93213&r2=93214&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/conditional-expr.cpp (original)
+++ cfe/trunk/test/SemaCXX/conditional-expr.cpp Mon Jan 11 18:44:57 2010
@@ -7,8 +7,8 @@
struct ToBool { explicit operator bool(); };
struct B;
-struct A { A(); A(const B&); };
-struct B { operator A() const; };
+struct A { A(); A(const B&); }; // expected-note 2 {{candidate constructor}}
+struct B { operator A() const; }; // expected-note 2 {{candidate function}}
struct I { operator int(); };
struct J { operator I(); };
struct K { operator double(); };
@@ -50,8 +50,8 @@
enum Enum { EVal };
struct Ambig {
- operator short();
- operator signed char();
+ operator short(); // expected-note 2 {{candidate function}}
+ operator signed char(); // expected-note 2 {{candidate function}}
};
void test()
@@ -129,10 +129,10 @@
vfn pfn = i1 ? F() : test;
pfn = i1 ? test : F();
// these are ambiguous - better messages would be nice
- (void)(i1 ? A() : B()); // expected-error {{incompatible operand types}}
- (void)(i1 ? B() : A()); // expected-error {{incompatible operand types}}
- (void)(i1 ? 1 : Ambig()); // expected-error {{incompatible operand types}}
- (void)(i1 ? Ambig() : 1); // expected-error {{incompatible operand types}}
+ (void)(i1 ? A() : B()); // expected-error {{conversion from 'struct B' to 'struct A' is ambiguous}}
+ (void)(i1 ? B() : A()); // expected-error {{conversion from 'struct B' to 'struct A' is ambiguous}}
+ (void)(i1 ? 1 : Ambig()); // expected-error {{conversion from 'struct Ambig' to 'int' is ambiguous}}
+ (void)(i1 ? Ambig() : 1); // expected-error {{conversion from 'struct Ambig' to 'int' is ambiguous}}
// By the way, this isn't an lvalue:
&(i1 ? i1 : i2); // expected-error {{address expression must be an lvalue or a function designator}}
More information about the cfe-commits
mailing list