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 { public void testOverloadedCommaOpWithConstClassRef_334955() throws Exception {
parseAndCheckBindings(); 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))) { (((ICPPMethod) fn).isDestructor() || ASTInternal.isStatic(fn, false))) {
// 13.3.1-4 for static member functions, the implicit object parameter always matches, no cost // 13.3.1-4 for static member functions, the implicit object parameter always matches, no cost
cost = new Cost(impliedObjectType, implicitParameterType, Rank.IDENTITY); cost = new Cost(impliedObjectType, implicitParameterType, Rank.IDENTITY);
cost.setImpliedObject();
} else if (impliedObjectType == null) { } else if (impliedObjectType == null) {
return null; return null;
} else if (impliedObjectType.isSameType(implicitParameterType)) { } else if (impliedObjectType.isSameType(implicitParameterType)) {
cost = new Cost(impliedObjectType, implicitParameterType, Rank.IDENTITY); cost = new Cost(impliedObjectType, implicitParameterType, Rank.IDENTITY);
cost.setImpliedObject();
} else { } else {
cost = Conversions.checkImplicitConversionSequence(implicitParameterType, impliedObjectType, sourceIsLValue, UDCMode.FORBIDDEN, Context.IMPLICIT_OBJECT); 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)) { if (CPPTemplates.isDependentType(implicitParameterType) || CPPTemplates.isDependentType(impliedObjectType)) {
IType s= getNestedType(impliedObjectType, TDEF|REF|CVTYPE); IType s= getNestedType(impliedObjectType, TDEF|REF|CVTYPE);
IType t= getNestedType(implicitParameterType, 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" // ... and "cv1 T1" is reference-compatible with "cv2 T2"
Cost cost= isReferenceCompatible(cv1T1, cv2T2, isImpliedObject); Cost cost= isReferenceCompatible(cv1T1, cv2T2, isImpliedObject);
if (cost != null) { 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); cost.setReferenceBinding(refBindingType);
return cost; return cost;
} }
@ -237,7 +233,7 @@ public class Conversions {
// 13.3.3.1.7 no temporary object when converting the implicit object parameter // 13.3.3.1.7 no temporary object when converting the implicit object parameter
if (!isImpliedObject && ctx != Context.REQUIRE_DIRECT_BINDING) { if (!isImpliedObject && ctx != Context.REQUIRE_DIRECT_BINDING) {
if (isReferenceRelated(T1, T2) < 0 || compareQualifications(cv1T1, cv2T2) >= 0) { 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()) { if (cost.converts()) {
cost.setReferenceBinding(refBindingType); cost.setReferenceBinding(refBindingType);
} }
@ -248,7 +244,7 @@ public class Conversions {
} }
// Non-reference binding // 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 * 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) { if (source instanceof InitializerListType) {
return listInitializationSequence(((InitializerListType) source), target, udc, false); 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 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) if (cmp < 0)
return null; 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 cost= new Cost(cv2Source, cv1Target, Rank.IDENTITY);
cost.setQualificationAdjustment(cmp); cost.setQualificationAdjustment(cmp);
cost.setInheritanceDistance(inheritanceDist); if (inheritanceDist > 0) {
cost.setInheritanceDistance(inheritanceDist);
cost.setRank(Rank.CONVERSION);
}
if (isImpliedObject) {
cost.setImpliedObject();
}
return cost; return cost;
} }
/** /**
* [4] Standard Conversions * [4] Standard Conversions
* Computes the cost of using the standard conversion sequence from source to target. * 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); final Cost cost= new Cost(source, target, Rank.IDENTITY);
if (lvalue_to_rvalue(cost)) if (lvalue_to_rvalue(cost))
return cost; return cost;
@ -522,7 +517,7 @@ public class Conversions {
if (promotion(cost)) if (promotion(cost))
return cost; return cost;
if (conversion(cost, isImplicitThis)) if (conversion(cost))
return cost; return cost;
if (qualificationConversion(cost)) if (qualificationConversion(cost))
@ -1016,7 +1011,7 @@ public class Conversions {
* [4.10] Pointer conversions * [4.10] Pointer conversions
* [4.11] Pointer to member 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 s = cost.source;
final IType t = cost.target; final IType t = cost.target;
@ -1084,10 +1079,8 @@ public class Conversions {
return true; return true;
} }
if (depth > 0) { if (depth > 0) {
if (!forImplicitThis) { cost.setRank(Rank.CONVERSION);
cost.setRank(Rank.CONVERSION); cost.setInheritanceDistance(depth);
cost.setInheritanceDistance(depth);
}
CVQualifier cv= getCVQualifier(srcPtr.getType()); CVQualifier cv= getCVQualifier(srcPtr.getType());
cost.source= new CPPPointerType(addQualifiers(tgtPtrTgt, cv.isConst(), cv.isVolatile(), cv.isRestrict())); 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 DeferredUDC fDeferredUDC= DeferredUDC.NONE;
private int fQualificationAdjustments; private int fQualificationAdjustments;
private int fInheritanceDistance; private int fInheritanceDistance;
private boolean fImpliedObject;
private ICPPFunction fUserDefinedConversion; private ICPPFunction fUserDefinedConversion;
private ReferenceBinding fReferenceBinding; private ReferenceBinding fReferenceBinding;
@ -175,12 +176,25 @@ public class Cost {
// cannot compare costs with deferred user defined conversions // cannot compare costs with deferred user defined conversions
assert fDeferredUDC == DeferredUDC.NONE && other.fDeferredUDC == DeferredUDC.NONE; 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) if (cmp != 0)
return cmp; return cmp;
// rank is equal // rank is equal
if (fRank == Rank.USER_DEFINED_CONVERSION) { if (rank == Rank.USER_DEFINED_CONVERSION) {
// 13.3.3.1.10 // 13.3.3.1.10
if (isAmbiguousUDC() || other.isAmbiguousUDC()) if (isAmbiguousUDC() || other.isAmbiguousUDC())
return 0; return 0;
@ -195,9 +209,11 @@ public class Cost {
return cmp; return cmp;
} }
cmp= fInheritanceDistance - other.fInheritanceDistance; if (!ignoreInheritanceDist) {
if (cmp != 0) cmp= fInheritanceDistance - other.fInheritanceDistance;
return cmp; if (cmp != 0)
return cmp;
}
if (fReferenceBinding == ReferenceBinding.LVALUE_REF) { if (fReferenceBinding == ReferenceBinding.LVALUE_REF) {
if (other.fReferenceBinding == ReferenceBinding.RVALUE_REF_BINDS_RVALUE) if (other.fReferenceBinding == ReferenceBinding.RVALUE_REF_BINDS_RVALUE)
@ -291,4 +307,8 @@ public class Cost {
public ICPPFunction getSelectedFunction() { public ICPPFunction getSelectedFunction() {
return fSelectedFunction; return fSelectedFunction;
} }
public void setImpliedObject() {
fImpliedObject= true;
}
} }