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.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93214 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
John McCall 2010-01-12 00:44:57 +00:00
Родитель 1fc00e6e49
Коммит 1d31833450
10 изменённых файлов: 327 добавлений и 210 удалений

Просмотреть файл

@ -1044,6 +1044,9 @@ public:
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);

Просмотреть файл

@ -893,7 +893,7 @@ TryStaticImplicitCast(Sema &Self, Expr *&SrcExpr, QualType DestType,
/*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.

Просмотреть файл

@ -4389,8 +4389,7 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
= 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 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
// 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 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
// 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 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
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 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
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 @@ Sema::CheckReferenceInit(Expr *&Init, QualType DeclType,
/*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);
}
}

Просмотреть файл

@ -1075,7 +1075,7 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
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 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
/*ForceRValue=*/true,
/*InOverloadResolution=*/false);
}
if (ICS.ConversionKind == ImplicitConversionSequence::BadConversion) {
if (ICS.isBad()) {
ICS = TryImplicitConversion(From, ToType,
/*SuppressUserConversions=*/false,
AllowExplicit,
@ -1103,7 +1103,7 @@ bool
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))
@ -1158,6 +1158,12 @@ Sema::PerformImplicitConversion(Expr *&From, QualType ToType,
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");
return false;
@ -1474,14 +1480,18 @@ QualType Sema::CheckPointerToMemberOperands(
/// \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 @@ static bool TryClassUnification(Sema &Self, Expr *From, Expr *To,
/*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 @@ static bool FindConditionalOverload(Sema &Self, Expr *&LHS, Expr *&RHS,
/// 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 @@ static bool ConvertForConditional(Sema &Self, Expr *&E,
/*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 @@ QualType Sema::CXXCheckConditionalOperands(Expr *&Cond, Expr *&LHS, Expr *&RHS,
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 @@ QualType Sema::FindCompositePointerType(Expr *&E1, Expr *&E2) {
/*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 @@ QualType Sema::FindCompositePointerType(Expr *&E1, Expr *&E2) {
/*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))

Просмотреть файл

@ -670,7 +670,7 @@ void InitListChecker::CheckSubElementType(InitListExpr *IList,
/*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 @@ static void TryReferenceInitialization(Sema &S,
Sequence);
if (ConvOvlResult == OR_Success)
return;
if (ConvOvlResult != OR_No_Viable_Function) {
Sequence.SetOverloadFailure(
InitializationSequence::FK_ReferenceInitOverloadFailed,
ConvOvlResult);
}
}
}
@ -2384,7 +2389,7 @@ static void TryReferenceInitialization(Sema &S,
/*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
@ -2711,7 +2716,7 @@ static void TryUserDefinedConversion(Sema &S,
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 @@ static void TryImplicitConversion(Sema &S,
/*FIXME:InOverloadResolution=*/false,
/*UserCast=*/Kind.isExplicitCast());
if (ICS.ConversionKind == ImplicitConversionSequence::BadConversion) {
if (ICS.isBad()) {
Sequence.SetFailed(InitializationSequence::FK_ConversionFailed);
return;
}

Просмотреть файл

@ -145,15 +145,12 @@ ImplicitConversionRank StandardConversionSequence::getRank() const {
/// 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::isPointerConversionToBool() const {
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 @@ void ImplicitConversionSequence::DebugPrint() const {
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 @@ void ImplicitConversionSequence::DebugPrint() const {
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 @@ Sema::TryImplicitConversion(Expr* From, QualType ToType,
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 @@ Sema::TryImplicitConversion(Expr* From, QualType ToType,
(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 @@ Sema::TryImplicitConversion(Expr* From, QualType ToType,
// 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;
} else {
ICS.ConversionKind = ImplicitConversionSequence::BadConversion;
if (UserDefResult == OR_Ambiguous) {
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.ConversionFunctionSet.push_back(Cand->Function);
}
ICS.Ambiguous.addConversion(Cand->Function);
} else {
ICS.setBad();
}
return ICS;
@ -524,7 +541,7 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
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 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
// 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 @@ Sema::IsStandardConversion(Expr* From, QualType ToType,
if (CanonFrom != CanonTo)
return false;
SCS.ToTypePtr = FromType.getAsOpaquePtr();
SCS.setToType(FromType);
return true;
}
@ -1544,8 +1561,7 @@ OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType,
// 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 @@ OverloadingResult Sema::IsUserDefinedConversion(Expr *From, QualType ToType,
}
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 @@ Sema::CompareImplicitConversionSequences(const ImplicitConversionSequence& ICS1,
// conversion sequence than an ellipsis conversion sequence
// (13.3.3.1.3).
//
if (ICS1.ConversionKind < ICS2.ConversionKind)
// 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.ConversionKind < ICS1.ConversionKind)
} 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 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1,
// 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 @@ Sema::CompareStandardConversionSequences(const StandardConversionSequence& SCS1,
// 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 @@ Sema::CompareQualificationConversions(const StandardConversionSequence& SCS1,
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 @@ Sema::TryObjectArgumentInitialization(QualType FromType,
// 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 @@ Sema::TryObjectArgumentInitialization(QualType FromType,
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 @@ Sema::PerformObjectArgumentInitialization(Expr *&From, CXXMethodDecl *Method) {
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 @@ ImplicitConversionSequence Sema::TryContextuallyConvertToBool(Expr *From) {
/// 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 @@ Sema::AddOverloadCandidate(FunctionDecl *Function,
= 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 {
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 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, CXXRecordDecl *ActingContext,
// 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 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, CXXRecordDecl *ActingContext,
= 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 @@ Sema::AddMethodCandidate(CXXMethodDecl *Method, CXXRecordDecl *ActingContext,
// (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 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
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 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
// 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 @@ Sema::AddConversionCandidate(CXXConversionDecl *Conversion,
/*ForceRValue=*/false,
/*InOverloadResolution=*/false);
switch (ICS.ConversionKind) {
switch (ICS.getKind()) {
case ImplicitConversionSequence::StandardConversion:
Candidate.FinalConversion = ICS.Standard;
break;
@ -2844,7 +2845,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
// object parameter.
ImplicitConversionSequence ObjectInit
= TryObjectArgumentInitialization(ObjectType, Conversion, ActingContext);
if (ObjectInit.ConversionKind == ImplicitConversionSequence::BadConversion) {
if (ObjectInit.isBad()) {
Candidate.Viable = false;
return;
}
@ -2852,8 +2853,7 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
// 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 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
/*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 @@ void Sema::AddSurrogateCandidate(CXXConversionDecl *Conversion,
// (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 @@ void Sema::AddBuiltinCandidate(QualType ResultTy, QualType *ParamTys,
/*ForceRValue=*/false,
/*InOverloadResolution=*/false);
}
if (Candidate.Conversions[ArgIdx].ConversionKind
== ImplicitConversionSequence::BadConversion) {
if (Candidate.Conversions[ArgIdx].isBad()) {
Candidate.Viable = false;
break;
}
@ -4304,11 +4301,22 @@ void Sema::NoteOverloadCandidate(FunctionDecl *Fn) {
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 @@ void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand) {
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 @@ void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc,
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 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
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 @@ Sema::PrintOverloadCandidates(OverloadCandidateSet& CandidateSet,
// 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)
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;
}
}
}

Просмотреть файл

@ -149,6 +149,15 @@ namespace clang {
/// 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 @@ namespace clang {
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 @@ namespace clang {
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,11 +276,53 @@ namespace clang {
/// 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;
};
/// When ConversionKind == BadConversion due to multiple conversion
/// functions, this will list those functions.
llvm::SmallVector<FunctionDecl*, 4> ConversionFunctionSet;
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;
}
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
@ -280,6 +381,16 @@ namespace clang {
/// 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++

Просмотреть файл

@ -21,6 +21,13 @@ namespace test0 {
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 {

Просмотреть файл

@ -40,7 +40,7 @@ void foo1(C1 c1, int A::* pmf) {
}
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}}
}

Просмотреть файл

@ -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 @@ struct MixedFieldsDerived : MixedFields {
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 @@ void test()
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}}