1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-05 08:46:02 +02:00

Bug 458679 - Ranking list-initialization sequences with user-defined

conversions

Change-Id: Ia976acf656f3431f96880b32fedc575a56c4e86b
Signed-off-by: Nathan Ridge <zeratul976@hotmail.com>
This commit is contained in:
Nathan Ridge 2015-02-04 02:55:55 -05:00 committed by Gerrit Code Review @ Eclipse.org
parent 3cf7241ccb
commit 9ca379e67f
5 changed files with 69 additions and 37 deletions

View file

@ -8778,6 +8778,30 @@ public class AST2CPPTests extends AST2TestBase {
helper.assertProblem("waldo({1, 2, 3, 4})", "waldo", IProblemBinding.SEMANTIC_NAME_NOT_FOUND);
}
// namespace std {
// template<class E>
// class initializer_list {
// const E* _array;
// long unsigned int _len;
//
// initializer_list(const E* array, int len) {}
// };
// }
//
// template<typename T>
// struct A {
// A(std::initializer_list<T> list) {}
// };
//
// struct B {
// int b;
// };
//
// A<B> waldo({{0}, {0}});
public void testListInitialization_458679() throws Exception {
parseAndCheckImplicitNameBindings();
}
// namespace std {
// template<typename T> class initializer_list;
// }

View file

@ -128,14 +128,6 @@ public class AST2TemplateTests extends AST2TestBase {
return parseAndCheckBindings(code, CPP);
}
protected IASTTranslationUnit parseAndCheckImplicitNameBindings() throws Exception {
IASTTranslationUnit tu = parse(getAboveComment(), CPP, false, true);
NameCollector col = new NameCollector(true /* Visit implicit names */);
tu.accept(col);
assertNoProblemBindings(col);
return tu;
}
protected BindingAssertionHelper getAssertionHelper() throws ParserException, IOException {
String code= getAboveComment();
return new BindingAssertionHelper(code, true);

View file

@ -15,6 +15,8 @@
*******************************************************************************/
package org.eclipse.cdt.core.parser.tests.ast2;
import static org.eclipse.cdt.core.parser.ParserLanguage.CPP;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
@ -775,6 +777,14 @@ public class AST2TestBase extends BaseTestCase {
assertNoProblemBindings(col);
return tu;
}
final protected IASTTranslationUnit parseAndCheckImplicitNameBindings() throws Exception {
IASTTranslationUnit tu = parse(getAboveComment(), CPP, false, true);
NameCollector col = new NameCollector(true /* Visit implicit names */);
tu.accept(col);
assertNoProblemBindings(col);
return tu;
}
final protected void assertNoProblemBindings(NameCollector col) {
for (IASTName n : col.nameList) {

View file

@ -601,6 +601,11 @@ public class Conversions {
bestCost.setRank(Rank.NO_MATCH);
}
}
// This cost came from listInitializationSequence() with an std::initializer_list
// type as the list initialization target. From the point of view of the caller,
// however, the target is the class type, not std::initializer_list, so update it
// accordingly.
bestCost.setListInitializationTarget(t);
return bestCost;
}

View file

@ -200,6 +200,35 @@ public class Cost {
if (cmp != 0)
return cmp;
// [over.ics.rank] p3.3:
// 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);
}
}
}
}
// rank is equal
if (rank == Rank.USER_DEFINED_CONVERSION) {
// 13.3.3.1.10
@ -241,35 +270,7 @@ 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;
}