Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNathan Ridge2015-03-21 07:00:07 +0000
committerGerrit Code Review @ Eclipse.org2015-04-03 17:17:27 +0000
commit76f23d05c3a3cec7f9e4a46d462ef1ac6ae2e8da (patch)
tree8e3b27596ad2243053b7f6b40e1da53b019d4ab9
parentf93a835c69226c8c93c3dab3da1a17ca5200d8d0 (diff)
downloadorg.eclipse.cdt-76f23d05c3a3cec7f9e4a46d462ef1ac6ae2e8da.tar.gz
org.eclipse.cdt-76f23d05c3a3cec7f9e4a46d462ef1ac6ae2e8da.tar.xz
org.eclipse.cdt-76f23d05c3a3cec7f9e4a46d462ef1ac6ae2e8da.zip
Bug 462705 - Derived-to-base pointer conversion in conditional operator
Change-Id: I04f792ae9485f9fbc67a7fd3658ef571d1ae7d0c Signed-off-by: Nathan Ridge <zeratul976@hotmail.com>
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java13
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java62
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalConditional.java2
3 files changed, 55 insertions, 22 deletions
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java
index 854f30caf77..4dbc48a3fee 100644
--- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java
@@ -10651,6 +10651,19 @@ public class AST2CPPTests extends AST2TestBase {
public void testThrowExpressionInConditional_396663() throws Exception {
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>
// struct enable_if {
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java
index 70624d86462..4b99eb5d6d8 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java
@@ -1180,7 +1180,7 @@ public class Conversions {
* 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}.
*/
- public static IType compositePointerType(IType t1, IType t2) {
+ public static IType compositePointerType(IType t1, IType t2, IASTNode point) {
final boolean isPtr1 = t1 instanceof IPointerType;
if (isPtr1 || isNullPtr(t1)) {
if (isNullPointerConstant(t2)) {
@@ -1210,7 +1210,7 @@ public class Conversions {
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)
return null;
if (t == target1)
@@ -1220,7 +1220,7 @@ public class Conversions {
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);
t2= getNestedType(t2, TDEF | REF);
if (t1 instanceof IPointerType && t2 instanceof IPointerType) {
@@ -1234,7 +1234,7 @@ public class Conversions {
return null;
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)
return null;
if (p1target == merged && cv1.isAtLeastAsQualifiedAs(cv2))
@@ -1247,27 +1247,47 @@ public class Conversions {
final IType uq1= getNestedType(t1, TDEF|REF|CVTYPE);
final IType uq2= getNestedType(t2, TDEF|REF|CVTYPE);
- if (uq1 == null || ! uq1.isSameType(uq2))
+ if (uq1 == 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)
- return null;
+ if (uq1.isSameType(uq2)) {
+ if (uq1 == t1 && uq2 == t2)
+ return t1;
- if (cv1.isAtLeastAsQualifiedAs(cv2))
- return t1;
- if (cv2.isAtLeastAsQualifiedAs(cv1))
- return t2;
+ CVQualifier cv1= getCVQualifier(t1);
+ CVQualifier cv2= getCVQualifier(t2);
+ if (cv1 == cv2)
+ return t1;
+
+ if (!allcq)
+ return null;
- // One type is const the other is volatile.
- return new CPPQualifierType(uq1, true, true);
+ if (cv1.isAtLeastAsQualifiedAs(cv2))
+ 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,
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalConditional.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalConditional.java
index 1b6199f9a8b..43be81821aa 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalConditional.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalConditional.java
@@ -260,7 +260,7 @@ public class EvalConditional extends CPPDependentEvaluation {
} else {
fType= CPPArithmeticConversion.convertCppOperandTypes(IASTBinaryExpression.op_plus, t2, t3);
if (fType == null) {
- fType= Conversions.compositePointerType(t2, t3);
+ fType= Conversions.compositePointerType(t2, t3, point);
if (fType == null) {
fType= ProblemType.UNKNOWN_FOR_EXPRESSION;
}

Back to the top