1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-22 06:02:11 +02:00

Bug 462705 - Derived-to-base pointer conversion in conditional operator

Change-Id: I04f792ae9485f9fbc67a7fd3658ef571d1ae7d0c
Signed-off-by: Nathan Ridge <zeratul976@hotmail.com>
This commit is contained in:
Nathan Ridge 2015-03-21 03:00:07 -04:00 committed by Gerrit Code Review @ Eclipse.org
parent f93a835c69
commit 76f23d05c3
3 changed files with 55 additions and 22 deletions

View file

@ -10652,6 +10652,19 @@ public class AST2CPPTests extends AST2TestBase {
parseAndCheckBindings(getAboveComment(), CPP, true); parseAndCheckBindings(getAboveComment(), CPP, true);
} }
// struct A {};
//
// struct B : A {};
//
// void foo(A*);
//
// int main() {
// foo(true ? new A() : new B());
// }
public void testBasePointerConverstionInConditional_462705() throws Exception {
parseAndCheckBindings();
}
// template <bool> // template <bool>
// struct enable_if { // struct enable_if {
// }; // };

View file

@ -1180,7 +1180,7 @@ public class Conversions {
* Composite pointer type computed as described in 5.9-2 except that if the conversion to * Composite pointer type computed as described in 5.9-2 except that if the conversion to
* the pointer is not possible, the method returns {@code null}. * the pointer is not possible, the method returns {@code null}.
*/ */
public static IType compositePointerType(IType t1, IType t2) { public static IType compositePointerType(IType t1, IType t2, IASTNode point) {
final boolean isPtr1 = t1 instanceof IPointerType; final boolean isPtr1 = t1 instanceof IPointerType;
if (isPtr1 || isNullPtr(t1)) { if (isPtr1 || isNullPtr(t1)) {
if (isNullPointerConstant(t2)) { if (isNullPointerConstant(t2)) {
@ -1210,7 +1210,7 @@ public class Conversions {
return addQualifiers(p2, p1.isConst(), p1.isVolatile(), p1.isRestrict()); return addQualifiers(p2, p1.isConst(), p1.isVolatile(), p1.isRestrict());
} }
IType t= mergePointers(target1, target2, true); IType t= mergePointers(target1, target2, point, true, true);
if (t == null) if (t == null)
return null; return null;
if (t == target1) if (t == target1)
@ -1220,7 +1220,7 @@ public class Conversions {
return copyPointer(p1, t, false, false); return copyPointer(p1, t, false, false);
} }
private static IType mergePointers(IType t1, IType t2, boolean allcq) { private static IType mergePointers(IType t1, IType t2, IASTNode point, boolean allcq, boolean allowInheritance) {
t1= getNestedType(t1, TDEF | REF); t1= getNestedType(t1, TDEF | REF);
t2= getNestedType(t2, TDEF | REF); t2= getNestedType(t2, TDEF | REF);
if (t1 instanceof IPointerType && t2 instanceof IPointerType) { if (t1 instanceof IPointerType && t2 instanceof IPointerType) {
@ -1234,7 +1234,7 @@ public class Conversions {
return null; return null;
final IType p1target = p1.getType(); final IType p1target = p1.getType();
IType merged= mergePointers(p1target, p2.getType(), allcq && (cv1.isConst() || cv2.isConst())); IType merged= mergePointers(p1target, p2.getType(), point, allcq && (cv1.isConst() || cv2.isConst()), false);
if (merged == null) if (merged == null)
return null; return null;
if (p1target == merged && cv1.isAtLeastAsQualifiedAs(cv2)) if (p1target == merged && cv1.isAtLeastAsQualifiedAs(cv2))
@ -1247,9 +1247,11 @@ public class Conversions {
final IType uq1= getNestedType(t1, TDEF|REF|CVTYPE); final IType uq1= getNestedType(t1, TDEF|REF|CVTYPE);
final IType uq2= getNestedType(t2, TDEF|REF|CVTYPE); final IType uq2= getNestedType(t2, TDEF|REF|CVTYPE);
if (uq1 == null || ! uq1.isSameType(uq2)) if (uq1 == null) {
return null; return null;
}
if (uq1.isSameType(uq2)) {
if (uq1 == t1 && uq2 == t2) if (uq1 == t1 && uq2 == t2)
return t1; return t1;
@ -1268,6 +1270,24 @@ public class Conversions {
// One type is const the other is volatile. // One type is const the other is volatile.
return new CPPQualifierType(uq1, true, true); return new CPPQualifierType(uq1, true, true);
} else if (allowInheritance) {
// Allow for conversion from pointer-to-derived to pointer-to-base as per [conv.ptr] p3.
IType base;
if (SemanticUtil.calculateInheritanceDepth(uq1, uq2, point) > 0) {
base = uq2;
} else if (SemanticUtil.calculateInheritanceDepth(uq2, uq1, point) > 0) {
base = uq1;
} else {
return null;
}
CVQualifier cv1= getCVQualifier(t1);
CVQualifier cv2= getCVQualifier(t2);
if (cv1 == CVQualifier.NONE && cv2 == CVQualifier.NONE) {
return base;
}
return new CPPQualifierType(base, cv1.isConst() || cv2.isConst(), cv1.isVolatile() || cv2.isVolatile());
}
return null;
} }
public static IType copyPointer(final IPointerType p1, IType target, final boolean isConst, public static IType copyPointer(final IPointerType p1, IType target, final boolean isConst,

View file

@ -260,7 +260,7 @@ public class EvalConditional extends CPPDependentEvaluation {
} else { } else {
fType= CPPArithmeticConversion.convertCppOperandTypes(IASTBinaryExpression.op_plus, t2, t3); fType= CPPArithmeticConversion.convertCppOperandTypes(IASTBinaryExpression.op_plus, t2, t3);
if (fType == null) { if (fType == null) {
fType= Conversions.compositePointerType(t2, t3); fType= Conversions.compositePointerType(t2, t3, point);
if (fType == null) { if (fType == null) {
fType= ProblemType.UNKNOWN_FOR_EXPRESSION; fType= ProblemType.UNKNOWN_FOR_EXPRESSION;
} }