1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Bug 335387: Overload resolution and conversion on implied object.

This commit is contained in:
Markus Schorn 2011-01-26 15:38:07 +00:00
parent 855cfa3b48
commit 46a7cd35cd
4 changed files with 64 additions and 30 deletions

View file

@ -9345,4 +9345,21 @@ public class AST2CPPTests extends AST2BaseTest {
public void testOverloadedCommaOpWithConstClassRef_334955() throws Exception {
parseAndCheckBindings();
}
// struct OK {int ok;};
// struct NOK {};
//
// template<typename T> struct bos {
// NOK operator<<(const void*);
// };
// template <typename T> struct os : bos<T> {};
// OK operator<<(bos<char>&, const char*);
//
// void test() {
// os<char> ss;
// (ss << "").ok;
// }
public void testOverloadedOperatorWithInheritanceDistance_335387() throws Exception {
parseAndCheckBindings();
}
}

View file

@ -2560,13 +2560,17 @@ public class CPPSemantics {
(((ICPPMethod) fn).isDestructor() || ASTInternal.isStatic(fn, false))) {
// 13.3.1-4 for static member functions, the implicit object parameter always matches, no cost
cost = new Cost(impliedObjectType, implicitParameterType, Rank.IDENTITY);
cost.setImpliedObject();
} else if (impliedObjectType == null) {
return null;
} else if (impliedObjectType.isSameType(implicitParameterType)) {
cost = new Cost(impliedObjectType, implicitParameterType, Rank.IDENTITY);
cost.setImpliedObject();
} else {
cost = Conversions.checkImplicitConversionSequence(implicitParameterType, impliedObjectType, sourceIsLValue, UDCMode.FORBIDDEN, Context.IMPLICIT_OBJECT);
if (!cost.converts()) {
if (cost.converts()) {
cost.setImpliedObject();
} else {
if (CPPTemplates.isDependentType(implicitParameterType) || CPPTemplates.isDependentType(impliedObjectType)) {
IType s= getNestedType(impliedObjectType, TDEF|REF|CVTYPE);
IType t= getNestedType(implicitParameterType, TDEF|REF|CVTYPE);

View file

@ -130,10 +130,6 @@ public class Conversions {
// ... and "cv1 T1" is reference-compatible with "cv2 T2"
Cost cost= isReferenceCompatible(cv1T1, cv2T2, isImpliedObject);
if (cost != null) {
// [13.3.3.1.4-1] direct binding has either identity or conversion rank.
if (cost.getInheritanceDistance() > 0) {
cost.setRank(Rank.CONVERSION);
}
cost.setReferenceBinding(refBindingType);
return cost;
}
@ -237,7 +233,7 @@ public class Conversions {
// 13.3.3.1.7 no temporary object when converting the implicit object parameter
if (!isImpliedObject && ctx != Context.REQUIRE_DIRECT_BINDING) {
if (isReferenceRelated(T1, T2) < 0 || compareQualifications(cv1T1, cv2T2) >= 0) {
Cost cost= nonReferenceConversion(valueCat, cv2T2, T1, udc, false);
Cost cost= nonReferenceConversion(valueCat, cv2T2, T1, udc);
if (cost.converts()) {
cost.setReferenceBinding(refBindingType);
}
@ -248,7 +244,7 @@ public class Conversions {
}
// Non-reference binding
return nonReferenceConversion(valueCat, exprType, T1, udc, isImpliedObject);
return nonReferenceConversion(valueCat, exprType, T1, udc);
}
/**
@ -301,7 +297,7 @@ public class Conversions {
/**
* 8.5-16
*/
private static Cost nonReferenceConversion(ValueCategory valueCat, IType source, IType target, UDCMode udc, boolean isImpliedObject) throws DOMException {
private static Cost nonReferenceConversion(ValueCategory valueCat, IType source, IType target, UDCMode udc) throws DOMException {
if (source instanceof InitializerListType) {
return listInitializationSequence(((InitializerListType) source), target, udc, false);
}
@ -334,7 +330,7 @@ public class Conversions {
return initializationByConversion(valueCat, source, (ICPPClassType) uqSource, target, udc == UDCMode.DEFER);
}
return checkStandardConversionSequence(uqSource, target, isImpliedObject);
return checkStandardConversionSequence(uqSource, target);
}
/**
@ -496,25 +492,24 @@ public class Conversions {
if (cmp < 0)
return null;
// 7.3.3.13 for overload resolution the implicit this pointer is treated as if
// it were a pointer to the derived class
if (isImpliedObject)
inheritanceDist= 0;
Cost cost= new Cost(cv2Source, cv1Target, Rank.IDENTITY);
cost.setQualificationAdjustment(cmp);
cost.setInheritanceDistance(inheritanceDist);
if (inheritanceDist > 0) {
cost.setInheritanceDistance(inheritanceDist);
cost.setRank(Rank.CONVERSION);
}
if (isImpliedObject) {
cost.setImpliedObject();
}
return cost;
}
/**
* [4] Standard Conversions
* Computes the cost of using the standard conversion sequence from source to target.
* @param isImplicitThis handles the special case when members of different
* classes are nominated via using-declarations. In such a situation the derived to
* base conversion does not cause any costs.
*/
private static final Cost checkStandardConversionSequence(IType source, IType target, boolean isImplicitThis) {
private static final Cost checkStandardConversionSequence(IType source, IType target) {
final Cost cost= new Cost(source, target, Rank.IDENTITY);
if (lvalue_to_rvalue(cost))
return cost;
@ -522,7 +517,7 @@ public class Conversions {
if (promotion(cost))
return cost;
if (conversion(cost, isImplicitThis))
if (conversion(cost))
return cost;
if (qualificationConversion(cost))
@ -1016,7 +1011,7 @@ public class Conversions {
* [4.10] Pointer conversions
* [4.11] Pointer to member conversions
*/
private static final boolean conversion(Cost cost, boolean forImplicitThis){
private static final boolean conversion(Cost cost){
final IType s = cost.source;
final IType t = cost.target;
@ -1084,10 +1079,8 @@ public class Conversions {
return true;
}
if (depth > 0) {
if (!forImplicitThis) {
cost.setRank(Rank.CONVERSION);
cost.setInheritanceDistance(depth);
}
cost.setRank(Rank.CONVERSION);
cost.setInheritanceDistance(depth);
CVQualifier cv= getCVQualifier(srcPtr.getType());
cost.source= new CPPPointerType(addQualifiers(tgtPtrTgt, cv.isConst(), cv.isVolatile(), cv.isRestrict()));
}

View file

@ -89,6 +89,7 @@ public class Cost {
private DeferredUDC fDeferredUDC= DeferredUDC.NONE;
private int fQualificationAdjustments;
private int fInheritanceDistance;
private boolean fImpliedObject;
private ICPPFunction fUserDefinedConversion;
private ReferenceBinding fReferenceBinding;
@ -175,12 +176,25 @@ public class Cost {
// cannot compare costs with deferred user defined conversions
assert fDeferredUDC == DeferredUDC.NONE && other.fDeferredUDC == DeferredUDC.NONE;
int cmp= fRank.compareTo(other.fRank);
// 7.3.3.13 (using declarations in classes):
// for overload resolution the implicit this pointer
// is treated as if it were a pointer to the derived class
final boolean ignoreInheritanceDist= fImpliedObject && other.fImpliedObject;
Rank rank = fRank;
Rank otherRank = other.fRank;
if (ignoreInheritanceDist) {
if (rank == Rank.CONVERSION)
rank= Rank.IDENTITY;
if (otherRank == Rank.CONVERSION)
otherRank= Rank.IDENTITY;
}
int cmp= rank.compareTo(otherRank);
if (cmp != 0)
return cmp;
// rank is equal
if (fRank == Rank.USER_DEFINED_CONVERSION) {
if (rank == Rank.USER_DEFINED_CONVERSION) {
// 13.3.3.1.10
if (isAmbiguousUDC() || other.isAmbiguousUDC())
return 0;
@ -195,9 +209,11 @@ public class Cost {
return cmp;
}
cmp= fInheritanceDistance - other.fInheritanceDistance;
if (cmp != 0)
return cmp;
if (!ignoreInheritanceDist) {
cmp= fInheritanceDistance - other.fInheritanceDistance;
if (cmp != 0)
return cmp;
}
if (fReferenceBinding == ReferenceBinding.LVALUE_REF) {
if (other.fReferenceBinding == ReferenceBinding.RVALUE_REF_BINDS_RVALUE)
@ -291,4 +307,8 @@ public class Cost {
public ICPPFunction getSelectedFunction() {
return fSelectedFunction;
}
public void setImpliedObject() {
fImpliedObject= true;
}
}