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

Bug 439477 - Ranking list-initialization sequences

Change-Id: I4c0dd621f91830ab1852abd1340b23e39a7dc4eb
Signed-off-by: Nathan Ridge <zeratul976@hotmail.com>
Reviewed-on: https://git.eclipse.org/r/34543
Reviewed-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
Tested-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
This commit is contained in:
Nathan Ridge 2014-10-08 04:03:35 -04:00 committed by Sergey Prigogin
parent 06d5c452ce
commit d9cefc1e0c
3 changed files with 97 additions and 1 deletions

View file

@ -8604,6 +8604,43 @@ public class AST2CPPTests extends AST2TestBase {
bh.assertNonProblem("fH({1})", 2);
}
// namespace std {
// template <typename T> class initializer_list;
// }
// void waldo(int);
// void waldo(std::initializer_list<int>);
// void foo() {
// waldo({});
// waldo({1});
// waldo({short(1)});
// waldo({1, 2});
// }
public void testListInitialization_439477a() throws Exception {
parseAndCheckBindings();
}
// void waldo(int const (&)[2]);
// void waldo(int const (&)[3]);
// void foo1() {
// waldo({1, 2}); // should resolve to waldo(int const (&)[2])
// waldo({1, 2, 3}); // should resolve to waldo(int const (&)[3])
// waldo({1, 2, 3, 4}); // should not resolve
// }
public void testListInitialization_439477b() throws Exception {
BindingAssertionHelper helper = getAssertionHelper();
ICPPFunction def1 = helper.assertNonProblem("waldo(int const (&)[2])", "waldo");
ICPPFunction def2 = helper.assertNonProblem("waldo(int const (&)[3])", "waldo");
ICPPFunction call1 = helper.assertNonProblem("waldo({1, 2})", "waldo");
ICPPFunction call2 = helper.assertNonProblem("waldo({1, 2, 3})", "waldo");
assertEquals(call1, def1);
assertEquals(call2, def2);
helper.assertProblem("waldo({1, 2, 3, 4})", "waldo", IProblemBinding.SEMANTIC_NAME_NOT_FOUND);
}
// namespace std {
// template<typename T> class initializer_list;
// }

View file

@ -342,7 +342,25 @@ public class Conversions {
* 13.3.3.1.5 List-initialization sequence [over.ics.list]
*/
static Cost listInitializationSequence(EvalInitList arg, IType target, UDCMode udc, boolean isDirect, IASTNode point) throws DOMException {
Cost result = listInitializationSequenceHelper(arg, target, udc, isDirect, point);
result.setListInitializationTarget(target);
return result;
}
static Cost listInitializationSequenceHelper(EvalInitList arg, IType target, UDCMode udc, boolean isDirect, IASTNode point) throws DOMException {
IType listType= getInitListType(target);
if (listType == null && target instanceof IArrayType) {
Long arraySize = ((IArrayType) target).getSize().numericalValue();
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.getTypeOrFunctionSet(point), target, Rank.IDENTITY);

View file

@ -15,6 +15,7 @@
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IArrayType;
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
import org.eclipse.cdt.core.dom.ast.IEnumeration;
import org.eclipse.cdt.core.dom.ast.IType;
@ -93,8 +94,15 @@ public class Cost {
private boolean fImpliedObject;
private ICPPFunction fUserDefinedConversion;
private ReferenceBinding fReferenceBinding;
private boolean fCouldNarrow;
// For a list-initialization sequence, 'target' is not always the original
// target type. Specifically, for an original target type of
// std::initializer_list<T> or array of T, 'target' will be T, but we need
// to know the original target as well so we store it here.
// This will be null iff. this is not a list-initialization sequence.
private IType fListInitializationTarget;
private ICPPFunction fSelectedFunction; // For targeted functions
public Cost(IType s, IType t, Rank rank) {
@ -233,6 +241,35 @@ public class Cost {
if ((other.fQualificationAdjustments & qdiff) == 0)
return 1;
}
// [over.ics.rank] p3:
// List-initialization sequence L1 is a better conversion sequence than
// list-initialization sequence L2 if
if (fListInitializationTarget != null && other.fListInitializationTarget != null) {
// - L1 converts to std::initializer_list<X> for some X and L2 does not,
// or if not that,
IType initListType = Conversions.getInitListType(fListInitializationTarget);
IType otherInitListType = Conversions.getInitListType(other.fListInitializationTarget);
if (initListType != null && otherInitListType == null) {
return -1;
} else if (initListType == null && otherInitListType != null) {
return 1;
}
// - L1 converts to type "array of N1 T", L2 converts to type "array of
// N2 T", and N1 is smaller than N2
if (fListInitializationTarget instanceof IArrayType && other.fListInitializationTarget instanceof IArrayType) {
IArrayType arrayType = (IArrayType) fListInitializationTarget;
IArrayType otherArrayType = (IArrayType) other.fListInitializationTarget;
if (arrayType.getType().isSameType(otherArrayType.getType())) {
Long size = arrayType.getSize().numericalValue();
Long otherSize = otherArrayType.getSize().numericalValue();
if (size != null && otherSize != null) {
return size.compareTo(otherSize);
}
}
}
}
return 0;
}
@ -352,4 +389,8 @@ public class Cost {
public void setImpliedObject() {
fImpliedObject= true;
}
public void setListInitializationTarget(IType target) {
fListInitializationTarget = target;
}
}