mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-30 12:25:35 +02:00
Bug 543038 - Implement brace elision for aggregate initialization
Change-Id: I72e92c8c196bf201c8edfde64598a7318d2fdfeb Signed-off-by: Hannes Vogt <hannes@havogt.de>
This commit is contained in:
parent
d8c2330efe
commit
0757b45da5
5 changed files with 347 additions and 114 deletions
|
@ -12843,11 +12843,150 @@ public class AST2CPPTests extends AST2CPPTestBase {
|
|||
//
|
||||
// int main() {
|
||||
// type(1, 2);
|
||||
// type{1, 2};
|
||||
// type(other_type());
|
||||
// }
|
||||
public void testCtorWithWrongArguments_543913() throws Exception {
|
||||
BindingAssertionHelper bh = getAssertionHelper();
|
||||
bh.assertImplicitName("type(1, 2)", 4, IProblemBinding.class);
|
||||
bh.assertImplicitName("type{1, 2}", 4, IProblemBinding.class);
|
||||
bh.assertImplicitName("type(other_type())", 4, IProblemBinding.class);
|
||||
}
|
||||
|
||||
// struct array{
|
||||
// int data[1];
|
||||
// };
|
||||
//
|
||||
// void foo(array) {}
|
||||
//
|
||||
// int main() {
|
||||
// array{{1}};
|
||||
// array{1};
|
||||
// array a = {1};
|
||||
// foo({1});
|
||||
// foo({{1}});
|
||||
// }
|
||||
public void testBraceElisionForAggregateInit0_SimpleValid_543038() throws Exception {
|
||||
parseAndCheckBindings();
|
||||
}
|
||||
|
||||
// struct array{
|
||||
// int data[1];
|
||||
// };
|
||||
//
|
||||
// void foo(array) {}
|
||||
//
|
||||
// int main() {
|
||||
// array{{1,2}};
|
||||
// array{1,2};
|
||||
// array a0 = {1,2};
|
||||
// foo({1,2});
|
||||
// foo({{1,2}});
|
||||
// }
|
||||
public void testBraceElisionForAggregateInit1_SimpleTooManyInitializers_543038() throws Exception {
|
||||
BindingAssertionHelper bh = getAssertionHelper();
|
||||
// bh.assertProblem("array{{1,2}}", 5); // TODO not implemented
|
||||
// bh.assertProblem("array{1,2}", 5); // TODO not implemented
|
||||
bh.assertImplicitName("a0", 2, IProblemBinding.class);
|
||||
bh.assertProblem("foo({1,2})", 3);
|
||||
bh.assertProblem("foo({{1,2}})", 3);
|
||||
}
|
||||
|
||||
// struct level0{
|
||||
// int a;
|
||||
// int b;
|
||||
// };
|
||||
//
|
||||
// struct level1{
|
||||
// public:
|
||||
// level1(level0 a): a(a){}
|
||||
// private:
|
||||
// level0 a;
|
||||
// };
|
||||
//
|
||||
// struct level2{
|
||||
// level1 data;
|
||||
// };
|
||||
//
|
||||
// void foo(level2) {}
|
||||
//
|
||||
// int main() {
|
||||
// level1{{1,2}}; // ok
|
||||
// foo({level1{{1,2}}}); // ok
|
||||
// level1{1,2}; // ERROR: calling level1 constructor, not aggregate init of level0
|
||||
// foo({{{1,2,3}}}); // ERROR: not aggregate init
|
||||
// }
|
||||
public void testBraceElisionForAggregateInit2_WithNonAggregate_543038() throws Exception {
|
||||
BindingAssertionHelper bh = getAssertionHelper();
|
||||
|
||||
bh.assertNonProblem("foo({level1{{1,2}}})", 3);
|
||||
|
||||
ICPPConstructor ctor = bh.assertNonProblem("level1(level0 a)", "level1");
|
||||
ICPPASTSimpleTypeConstructorExpression typeConstructorExpr = bh.assertNode("level1{{1,2}};", "level1{{1,2}}");
|
||||
IASTImplicitName[] implicitNames = ((IASTImplicitNameOwner) typeConstructorExpr).getImplicitNames();
|
||||
assertEquals(ctor, implicitNames[0].resolveBinding());
|
||||
|
||||
bh.assertImplicitName("level1{1,2};", 6, IProblemBinding.class);
|
||||
bh.assertProblem("foo({{{1,2,3}}}", 3);
|
||||
}
|
||||
|
||||
// struct array2D{
|
||||
// int data[2][3];
|
||||
// };
|
||||
//
|
||||
// void foo(array2D) {}
|
||||
//
|
||||
// int main() {
|
||||
// foo({{{1,2,3},{1,2,3}}}); // no elision
|
||||
// foo({{1,2,3,1,2,3}}); // eliding one level
|
||||
// foo({{1,2}}); // eliding one level, but with only 2 elements which seems to initialize the outer level
|
||||
// foo({1,2,3,1,2,3}); // eliding all levels
|
||||
// foo({{1,2,3},{1,2,3}}); // ERROR eliding outer-most is not allowed
|
||||
// }
|
||||
public void testBraceElisionForAggregateInit3_543038() throws Exception {
|
||||
BindingAssertionHelper bh = getAssertionHelper();
|
||||
bh.assertNonProblem("foo({{{1,2,3},{1,2,3}}});", 3);
|
||||
bh.assertNonProblem("foo({{1,2,3,1,2,3}});", 3);
|
||||
bh.assertNonProblem("foo({{1,2}});", 3);
|
||||
bh.assertNonProblem("foo({1,2,3,1,2,3});", 3);
|
||||
bh.assertProblem("foo({{1,2,3},{1,2,3}});", 3);
|
||||
}
|
||||
|
||||
// struct type{
|
||||
// type(int){};
|
||||
// };
|
||||
//
|
||||
// struct array{
|
||||
// type data[2];
|
||||
// };
|
||||
//
|
||||
// void foo(array){}
|
||||
//
|
||||
// int main() {
|
||||
// foo({type{1},type{2}});
|
||||
// foo({type{1}}); // ERROR: type is not default constructible
|
||||
// }
|
||||
public void testBraceElisionForAggregateInit4_nonDefaultConstructible_543038() throws Exception {
|
||||
BindingAssertionHelper bh = getAssertionHelper();
|
||||
bh.assertNonProblem("foo({type{1},type{2}});", 3);
|
||||
bh.assertProblem("foo({type{1}});", 3);
|
||||
}
|
||||
|
||||
// struct array2D{
|
||||
// int data[2][3];
|
||||
// };
|
||||
//
|
||||
// void foo(array2D) {}
|
||||
//
|
||||
// int main() {
|
||||
// foo({{{1,2,3},1,2,3}}); // ok: data[0] is initialized without elision, data[1] with elision
|
||||
// foo({{1,2,3,{1,2,3}}}); // ok: data[1] is initialized without elision, data[0] with elision
|
||||
// foo({{1,2,{1,2,3}}}); // ERROR: trying to initialize data[0][2] with {1,2,3}
|
||||
// }
|
||||
public void testBraceElisionForAggregateInit5_partlyEliding_543038() throws Exception {
|
||||
BindingAssertionHelper bh = getAssertionHelper();
|
||||
bh.assertNonProblem("foo({{{1,2,3},1,2,3}});", 3);
|
||||
bh.assertNonProblem("foo({{1,2,3,{1,2,3}}});", 3);
|
||||
bh.assertProblem("foo({{1,2,{1,2,3}}});", 3);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -150,12 +150,18 @@ public class ProblemBinding extends PlatformObject implements IProblemBinding, I
|
|||
|
||||
@Override
|
||||
public String getName() {
|
||||
return node instanceof IASTName ? new String(((IASTName) node).getSimpleID()) : CPPSemantics.EMPTY_NAME;
|
||||
if (node instanceof IASTName)
|
||||
return new String(((IASTName) node).getSimpleID());
|
||||
else
|
||||
return arg != null ? new String(arg) : CPPSemantics.EMPTY_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char[] getNameCharArray() {
|
||||
return node instanceof IASTName ? ((IASTName) node).getSimpleID() : CharArrayUtils.EMPTY;
|
||||
if (node instanceof IASTName)
|
||||
return ((IASTName) node).getSimpleID();
|
||||
else
|
||||
return arg != null ? arg : CharArrayUtils.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,182 @@
|
|||
/*******************************************************************************
|
||||
* This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License 2.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||
import org.eclipse.cdt.core.dom.ast.IArrayType;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.IValue;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
|
||||
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions.Context;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions.UDCMode;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.Rank;
|
||||
|
||||
class AggregateInitialization {
|
||||
private ICPPEvaluation[] fInitializers;
|
||||
private int fIndex = 0;
|
||||
|
||||
/**
|
||||
* Checks whether 'target' can be initialized from 'list' according to the rules for
|
||||
* aggregate initialization ([dcl.init.aggr]).
|
||||
*/
|
||||
public static Cost check(IType target, EvalInitList list) throws DOMException {
|
||||
return new AggregateInitialization().checkImpl(target, list);
|
||||
}
|
||||
|
||||
private AggregateInitialization() {
|
||||
}
|
||||
|
||||
private Cost checkImpl(IType target, EvalInitList list) throws DOMException {
|
||||
fInitializers = list.getClauses();
|
||||
fIndex = 0;
|
||||
|
||||
Cost worstCost = new Cost(list.getType(), target, Rank.IDENTITY);
|
||||
|
||||
Cost cost = checkInitializationOfElements(target, worstCost);
|
||||
if (!cost.converts())
|
||||
return cost;
|
||||
|
||||
if (fIndex < fInitializers.length)
|
||||
// p7: An initializer-list is ill-formed if the number of initializer-clauses exceeds
|
||||
// the number of members to initialize.
|
||||
return Cost.NO_CONVERSION;
|
||||
else
|
||||
return worstCost;
|
||||
}
|
||||
|
||||
/**
|
||||
* If no braces are elided, check initialization of element by taking the next clause from the EvalInitList,
|
||||
* else recurses into the subaggregate.
|
||||
*/
|
||||
private Cost checkElement(IType type, IValue initialValue, Cost worstCost) throws DOMException {
|
||||
if (fIndex >= fInitializers.length)
|
||||
// TODO for arrays we could short-circuit default init instead of trying to init each element
|
||||
return checkInitializationFromDefaultMemberInitializer(type, initialValue, worstCost);
|
||||
worstCost = new Cost(fInitializers[fIndex].getType(), type, Rank.IDENTITY);
|
||||
|
||||
if (fInitializers[fIndex].isInitializerList() || !isAggregate(type)) { // no braces are elided
|
||||
// p3: The elements of the initializer list are taken as initializers for the elements
|
||||
// of the aggregate, in order.
|
||||
ICPPEvaluation initializer = fInitializers[fIndex];
|
||||
fIndex++;
|
||||
Cost cost = Conversions.checkImplicitConversionSequence(type, initializer.getType(),
|
||||
initializer.getValueCategory(), UDCMode.ALLOWED, Context.ORDINARY);
|
||||
if (!cost.converts()) {
|
||||
return cost;
|
||||
}
|
||||
// If the initializer-clause is an expression and a narrowing conversion is
|
||||
// required to convert the expression, the program is ill-formed.
|
||||
if (!(initializer instanceof EvalInitList) && cost.isNarrowingConversion()) {
|
||||
return Cost.NO_CONVERSION;
|
||||
}
|
||||
if (cost.compareTo(worstCost) > 0) {
|
||||
worstCost = cost;
|
||||
}
|
||||
} else { // braces are elided: need to check on subaggregates
|
||||
Cost cost = checkInitializationOfElements(type, worstCost);
|
||||
if (!cost.converts())
|
||||
return cost;
|
||||
if (cost.compareTo(worstCost) > 0) {
|
||||
worstCost = cost;
|
||||
}
|
||||
}
|
||||
return worstCost;
|
||||
}
|
||||
|
||||
/**
|
||||
* checkElement() for each element of an array or each field of a class aggregate.
|
||||
*/
|
||||
private Cost checkInitializationOfElements(IType type, Cost worstCost) throws DOMException {
|
||||
if (type instanceof ICPPClassType && TypeTraits.isAggregateClass((ICPPClassType) type)) {
|
||||
ICPPField[] fields = getFieldsForAggregateInitialization((ICPPClassType) type);
|
||||
for (ICPPField field : fields) {
|
||||
Cost cost = checkElement(field.getType(), field.getInitialValue(), worstCost);
|
||||
if (!cost.converts())
|
||||
return cost;
|
||||
if (cost.compareTo(worstCost) > 0) {
|
||||
worstCost = cost;
|
||||
}
|
||||
}
|
||||
} else if (type instanceof IArrayType) {
|
||||
IArrayType arrayType = (IArrayType) type;
|
||||
Number arraySize = arrayType.getSize().numberValue();
|
||||
if (arraySize != null)
|
||||
for (long i = 0; i < arraySize.longValue(); i++) {
|
||||
Cost cost = checkElement(arrayType.getType(), null, worstCost);
|
||||
if (!cost.converts())
|
||||
return cost;
|
||||
if (cost.compareTo(worstCost) > 0) {
|
||||
worstCost = cost;
|
||||
}
|
||||
}
|
||||
}
|
||||
return worstCost;
|
||||
}
|
||||
|
||||
/**
|
||||
* p8: If there are fewer initializer-clauses than there are elements in the
|
||||
* aggregate, then each element not explicitly initialized shall be
|
||||
* initialized from its default member initializer or, if there is no
|
||||
* default member initializer, from an empty initializer list.
|
||||
*/
|
||||
private Cost checkInitializationFromDefaultMemberInitializer(IType type, IValue initialValue, Cost worstCost)
|
||||
throws DOMException {
|
||||
if (initialValue != null) {
|
||||
return worstCost; // has a default member initializer
|
||||
}
|
||||
|
||||
// p11: If an incomplete or empty initializer-list leaves a member of
|
||||
// reference type uninitialized, the program is ill-formed.
|
||||
IType fieldType = SemanticUtil.getNestedType(type, SemanticUtil.TDEF);
|
||||
if (fieldType instanceof ICPPReferenceType) {
|
||||
return Cost.NO_CONVERSION;
|
||||
}
|
||||
|
||||
// Empty initializer list
|
||||
EvalInitList emptyInit = new EvalInitList(ICPPEvaluation.EMPTY_ARRAY, CPPSemantics.getCurrentLookupPoint());
|
||||
Cost cost = Conversions.listInitializationSequence(emptyInit, fieldType, UDCMode.ALLOWED, false);
|
||||
return cost;
|
||||
}
|
||||
|
||||
private static boolean isAggregate(IType type) {
|
||||
return (type instanceof ICPPClassType && TypeTraits.isAggregateClass((ICPPClassType) type))
|
||||
|| type instanceof IArrayType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get those fields of 'targetClass' which participate in aggregate initialization.
|
||||
* These are the declared fields, excluding static fields and anonymous bit-fields
|
||||
* ([decl.init.aggr] p6).
|
||||
*/
|
||||
private static ICPPField[] getFieldsForAggregateInitialization(ICPPClassType targetClass) {
|
||||
ICPPField[] fields = targetClass.getDeclaredFields();
|
||||
ICPPField[] result = fields;
|
||||
int j = 0;
|
||||
for (int i = 0; i < fields.length; ++i) {
|
||||
// TODO: Check for anonymous bit-fields. ICPPField doesn't currently expose whether
|
||||
// it's a bit-field.
|
||||
if (fields[i].isStatic()) {
|
||||
if (fields == result) {
|
||||
result = new ICPPField[fields.length - 1];
|
||||
System.arraycopy(fields, 0, result, 0, i);
|
||||
}
|
||||
} else if (fields != result) {
|
||||
result[j] = fields[i];
|
||||
++j;
|
||||
}
|
||||
}
|
||||
return ArrayUtil.trim(result);
|
||||
}
|
||||
|
||||
}
|
|
@ -49,7 +49,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||
|
@ -58,7 +57,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPPointerToMemberType;
|
|||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
|
||||
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ArithmeticConversion;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
|
||||
|
@ -334,97 +332,6 @@ public class Conversions {
|
|||
return checkStandardConversionSequence(uqSource, target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get those fields of 'targetClass' which participate in aggregate initialization.
|
||||
* These are the declared fields, excluding static fields and anonymous bit-fields
|
||||
* ([decl.init.aggr] p6).
|
||||
*/
|
||||
static ICPPField[] getFieldsForAggregateInitialization(ICPPClassType targetClass) {
|
||||
ICPPField[] fields = targetClass.getDeclaredFields();
|
||||
ICPPField[] result = fields;
|
||||
int j = 0;
|
||||
for (int i = 0; i < fields.length; ++i) {
|
||||
// TODO: Check for anonymous bit-fields. ICPPField doesn't currently expose whether
|
||||
// it's a bit-field.
|
||||
if (fields[i].isStatic()) {
|
||||
if (fields == result) {
|
||||
result = new ICPPField[fields.length - 1];
|
||||
System.arraycopy(fields, 0, result, 0, i);
|
||||
}
|
||||
} else if (fields != result) {
|
||||
result[j] = fields[i];
|
||||
++j;
|
||||
}
|
||||
}
|
||||
return ArrayUtil.trim(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether 'targetClass' can be initialized from 'list' according to the rules for
|
||||
* aggregate initialization ([dcl.init.aggr]).
|
||||
*/
|
||||
static boolean checkAggregateInitialization(EvalInitList list, ICPPClassType targetClass) throws DOMException {
|
||||
ICPPField[] fields = getFieldsForAggregateInitialization(targetClass);
|
||||
ICPPEvaluation[] initializers = list.getClauses();
|
||||
|
||||
// p7: An initializer-list is ill-formed if the number of initializer-clauses exceeds
|
||||
// the number of members to initialize.
|
||||
if (initializers.length > fields.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// p3: The elements of the initializer list are taken as initializers for the elements
|
||||
// of the aggregate, in order.
|
||||
int i = 0;
|
||||
for (; i < initializers.length; ++i) {
|
||||
ICPPEvaluation initializer = initializers[i];
|
||||
ICPPField field = fields[i];
|
||||
|
||||
// Each element is copy-initialized from the corresponding initializer-clause.
|
||||
Cost cost = checkImplicitConversionSequence(field.getType(), initializer.getType(),
|
||||
initializer.getValueCategory(), UDCMode.ALLOWED, Context.ORDINARY);
|
||||
if (!cost.converts()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the initializer-clause is an expression and a narrowing conversion is
|
||||
// required to convert the expression, the program is ill-formed.
|
||||
if (!(initializer instanceof EvalInitList) && cost.isNarrowingConversion()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// p8: If there are fewer initializer-clauses than there are elements in the
|
||||
// aggregate, then each element not explicitly initialized shall be
|
||||
// initialized from its default member initializer or, if there is no
|
||||
// default member initializer, from an empty initializer list.
|
||||
for (; i < fields.length; ++i) {
|
||||
ICPPField field = fields[i];
|
||||
IValue initialValue = field.getInitialValue();
|
||||
if (initialValue != null) {
|
||||
continue; // has a default member initializer
|
||||
}
|
||||
|
||||
// p11: If an incomplete or empty initializer-list leaves a member of
|
||||
// reference type uninitialized, the program is ill-formed.
|
||||
IType fieldType = SemanticUtil.getNestedType(field.getType(), TDEF);
|
||||
if (fieldType instanceof ICPPReferenceType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Empty initializer list
|
||||
EvalInitList emptyInit = new EvalInitList(ICPPEvaluation.EMPTY_ARRAY, CPPSemantics.getCurrentLookupPoint());
|
||||
Cost cost = listInitializationSequence(emptyInit, fieldType, UDCMode.ALLOWED, false);
|
||||
if (!cost.converts()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Implement brace elision rules.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 13.3.3.1.5 List-initialization sequence [over.ics.list]
|
||||
*/
|
||||
|
@ -438,22 +345,9 @@ public class Conversions {
|
|||
static Cost listInitializationSequenceHelper(EvalInitList arg, IType target, UDCMode udc, boolean isDirect)
|
||||
throws DOMException {
|
||||
IType listType = getInitListType(target);
|
||||
if (listType == null && target instanceof IArrayType) {
|
||||
Number arraySize = ((IArrayType) target).getSize().numberValue();
|
||||
if (arraySize != null) {
|
||||
IType elementType = ((IArrayType) target).getType();
|
||||
// TODO(nathanridge): If there are fewer initializer clauses than the array size,
|
||||
// then the element type is required to be default-constructible.
|
||||
if (arg.getClauses().length <= arraySize.longValue()) {
|
||||
listType = elementType;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (listType != null) {
|
||||
ICPPEvaluation[] clauses = arg.getClauses();
|
||||
Cost worstCost = new Cost(arg.getType(), target, Rank.IDENTITY);
|
||||
for (ICPPEvaluation clause : clauses) {
|
||||
for (ICPPEvaluation clause : arg.getClauses()) {
|
||||
Cost cost = checkImplicitConversionSequence(listType, clause.getType(), clause.getValueCategory(),
|
||||
UDCMode.ALLOWED, Context.ORDINARY);
|
||||
if (!cost.converts())
|
||||
|
@ -467,6 +361,8 @@ public class Conversions {
|
|||
}
|
||||
}
|
||||
return worstCost;
|
||||
} else if (target instanceof IArrayType) {
|
||||
return AggregateInitialization.check(target, arg);
|
||||
}
|
||||
|
||||
IType noCVTarget = getNestedType(target, CVTYPE | TDEF);
|
||||
|
@ -475,10 +371,12 @@ public class Conversions {
|
|||
return Cost.NO_CONVERSION;
|
||||
|
||||
ICPPClassType classTarget = (ICPPClassType) noCVTarget;
|
||||
if (TypeTraits.isAggregateClass(classTarget) && checkAggregateInitialization(arg, classTarget)) {
|
||||
Cost cost = new Cost(arg.getType(), target, Rank.IDENTITY);
|
||||
cost.setUserDefinedConversion(null);
|
||||
return cost;
|
||||
if (TypeTraits.isAggregateClass(classTarget)) {
|
||||
Cost cost = AggregateInitialization.check(classTarget, arg);
|
||||
if (cost.converts()) {
|
||||
cost.setUserDefinedConversion(null);
|
||||
return cost;
|
||||
}
|
||||
}
|
||||
return listInitializationOfClass(arg, classTarget, isDirect, udc == UDCMode.DEFER);
|
||||
}
|
||||
|
|
|
@ -272,7 +272,7 @@ public class EvalTypeId extends CPPDependentEvaluation {
|
|||
ICPPClassType classType = (ICPPClassType) simplifiedType;
|
||||
ICPPEvaluation[] arguments = fArguments;
|
||||
ICPPConstructor[] constructors = classType.getConstructors();
|
||||
if (arguments.length == 1 && arguments[0] instanceof EvalInitList) {
|
||||
if (arguments.length == 1 && arguments[0] instanceof EvalInitList && !fUsesBracedInitList) {
|
||||
// List-initialization of a class (dcl.init.list-3).
|
||||
if (TypeTraits.isAggregateClass(classType)) {
|
||||
// Pretend that aggregate initialization is calling the default constructor.
|
||||
|
@ -299,10 +299,18 @@ public class EvalTypeId extends CPPDependentEvaluation {
|
|||
if (binding instanceof ICPPFunction) {
|
||||
return (ICPPFunction) binding;
|
||||
}
|
||||
// TODO check aggregate initialization
|
||||
if (fUsesBracedInitList && allConstructorsAreCompilerGenerated(constructors)) {
|
||||
return AGGREGATE_INITIALIZATION;
|
||||
}
|
||||
if (binding instanceof IProblemBinding && !(binding instanceof ICPPFunction))
|
||||
return new CPPFunction.CPPFunctionProblem(null, ((IProblemBinding) binding).getID(),
|
||||
classType.getNameCharArray());
|
||||
} catch (DOMException e) {
|
||||
CCorePlugin.log(e);
|
||||
}
|
||||
|
||||
// TODO check aggregate initialization
|
||||
if (fUsesBracedInitList && allConstructorsAreCompilerGenerated(constructors)) {
|
||||
return AGGREGATE_INITIALIZATION;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue