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:
parent
06d5c452ce
commit
d9cefc1e0c
3 changed files with 97 additions and 1 deletions
|
@ -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;
|
||||
// }
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue