diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java index 10caf4e5477..d9e51074ed2 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java @@ -7658,4 +7658,15 @@ public class AST2Tests extends AST2TestBase { labelResolutionHelper(getAssertionHelper(C)); labelResolutionHelper(getAssertionHelper(CPP)); } + + // int arr1[5]; + // int arr2[5]; + // void foo(bool cond) { + // cond ? arr1 : arr2; + // } + public void testArrayTypesInConditionalExpression_520049() throws Exception { + BindingAssertionHelper helper = getAssertionHelper(C); + IASTConditionalExpression expr = helper.assertNode("cond ? arr1 : arr2"); + assertSameType(expr.getExpressionType(), CommonCTypes.pointerToInt); + } } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/SemanticTestBase.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/SemanticTestBase.java index fccc174b5d2..b33723d6f6a 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/SemanticTestBase.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/SemanticTestBase.java @@ -47,6 +47,7 @@ public class SemanticTestBase extends BaseTestCase { protected static class CommonCTypes { public static IType pointerToVoid = pointerTo(CBasicType.VOID); public static IType pointerToConstVoid = pointerTo(constOf(CBasicType.VOID)); + public static IType pointerToInt = pointerTo(CBasicType.INT); public static IType pointerToConstInt = pointerTo(constOf(CBasicType.INT)); public static IType pointerToVolatileInt = pointerTo(volatileOf(CBasicType.INT)); public static IType pointerToConstVolatileInt = pointerTo(constVolatileOf(CBasicType.INT)); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTBinaryExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTBinaryExpression.java index 8438c9d288b..96b3b0c08fd 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTBinaryExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTBinaryExpression.java @@ -232,11 +232,11 @@ public class CASTBinaryExpression extends ASTNode case IASTBinaryExpression.op_plus: if (type1 instanceof IArrayType) { - return arrayTypeToPointerType((ICArrayType) type1); + return Conversions.arrayTypeToPointerType((ICArrayType) type1); } else if (type2 instanceof IPointerType) { return restoreTypedefs(type2, originalType2); } else if (type2 instanceof IArrayType) { - return arrayTypeToPointerType((ICArrayType) type2); + return Conversions.arrayTypeToPointerType((ICArrayType) type2); } break; @@ -252,13 +252,6 @@ public class CASTBinaryExpression extends ASTNode return restoreTypedefs(type1, originalType1); } - private IType arrayTypeToPointerType(ICArrayType type) { - return new CPointerType(type.getType(), - (type.isConst() ? CPointerType.IS_CONST : 0) | - (type.isRestrict() ? CPointerType.IS_RESTRICT : 0) | - (type.isVolatile() ? CPointerType.IS_VOLATILE : 0)); - } - @Override public boolean isLValue() { switch (getOperator()) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTConditionalExpression.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTConditionalExpression.java index 410dd600bb7..f558fb17594 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTConditionalExpression.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTConditionalExpression.java @@ -21,6 +21,7 @@ import org.eclipse.cdt.core.dom.ast.IBasicType; import org.eclipse.cdt.core.dom.ast.ICompositeType; import org.eclipse.cdt.core.dom.ast.IPointerType; import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.c.ICArrayType; import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent; import org.eclipse.cdt.internal.core.dom.parser.ProblemType; @@ -198,6 +199,14 @@ public class CASTConditionalExpression extends ASTNode implements return positiveType; } } + + // Perform array-to-pointer decay on the operand types. + if (positiveType instanceof ICArrayType) { + positiveType = Conversions.arrayTypeToPointerType(((ICArrayType) positiveType)); + } + if (negativeType instanceof ICArrayType) { + negativeType = Conversions.arrayTypeToPointerType(((ICArrayType) negativeType)); + } // [6.5.15] p6: If both the second and third operands are pointers or one is a null pointer // constant and the other is a pointer, the result type is a pointer to a type qualified with @@ -217,11 +226,12 @@ public class CASTConditionalExpression extends ASTNode implements IType positivePointee = CVisitor.unwrapCV(positivePointeeCV); IType negativePointee = CVisitor.unwrapCV(negativePointeeCV); IType resultPointee; - if (positivePointee.isSameType(CBasicType.VOID) || negativePointee.isSameType(CBasicType.VOID)) { - resultPointee = CBasicType.VOID; - } else { - // TODO: Implement checking for compatible types and computing the composite type. + if (positivePointee.isSameType(negativePointee)) { resultPointee = negativePointee; + } else if (positivePointee.isSameType(CBasicType.VOID) || negativePointee.isSameType(CBasicType.VOID)) { + resultPointee = CBasicType.VOID; + } else { + return ProblemType.UNKNOWN_FOR_EXPRESSION; } return new CPointerType( ExpressionTypes.restoreCV(resultPointee, positivePointeeCV, negativePointeeCV), 0); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/Conversions.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/Conversions.java new file mode 100644 index 00000000000..aa039f47147 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/Conversions.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2017 Nathan Ridge. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + *******************************************************************************/ +package org.eclipse.cdt.internal.core.dom.parser.c; + +import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.c.ICArrayType; + +/** + * Routines related to conversions. + */ +public class Conversions { + /** + * Perform array-to-pointer decay. + */ + public static IType arrayTypeToPointerType(ICArrayType type) { + return new CPointerType(type.getType(), + (type.isConst() ? CPointerType.IS_CONST : 0) | + (type.isRestrict() ? CPointerType.IS_RESTRICT : 0) | + (type.isVolatile() ? CPointerType.IS_VOLATILE : 0)); + } +}