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:
parent
f93a835c69
commit
76f23d05c3
3 changed files with 55 additions and 22 deletions
|
@ -10651,6 +10651,19 @@ public class AST2CPPTests extends AST2TestBase {
|
||||||
public void testThrowExpressionInConditional_396663() throws Exception {
|
public void testThrowExpressionInConditional_396663() throws Exception {
|
||||||
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 {
|
||||||
|
|
|
@ -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,27 +1247,47 @@ 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 == t1 && uq2 == t2)
|
|
||||||
return t1;
|
|
||||||
|
|
||||||
CVQualifier cv1= getCVQualifier(t1);
|
|
||||||
CVQualifier cv2= getCVQualifier(t2);
|
|
||||||
if (cv1 == cv2)
|
|
||||||
return t1;
|
|
||||||
|
|
||||||
if (!allcq)
|
if (uq1.isSameType(uq2)) {
|
||||||
return null;
|
if (uq1 == t1 && uq2 == t2)
|
||||||
|
return t1;
|
||||||
|
|
||||||
if (cv1.isAtLeastAsQualifiedAs(cv2))
|
CVQualifier cv1= getCVQualifier(t1);
|
||||||
return t1;
|
CVQualifier cv2= getCVQualifier(t2);
|
||||||
if (cv2.isAtLeastAsQualifiedAs(cv1))
|
if (cv1 == cv2)
|
||||||
return t2;
|
return t1;
|
||||||
|
|
||||||
|
if (!allcq)
|
||||||
|
return null;
|
||||||
|
|
||||||
// One type is const the other is volatile.
|
if (cv1.isAtLeastAsQualifiedAs(cv2))
|
||||||
return new CPPQualifierType(uq1, true, true);
|
return t1;
|
||||||
|
if (cv2.isAtLeastAsQualifiedAs(cv1))
|
||||||
|
return t2;
|
||||||
|
|
||||||
|
// One type is const the other is volatile.
|
||||||
|
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,
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue