diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index b5d6d053b34..8af94279ad4 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -8848,7 +8848,7 @@ public void testListInitialization_302412b() throws Exception { // h({ "foo" }); // OK: h(C(std::string("foo"))) // i({ { 1, 2 }, { "bar" } }); // OK: i(D(A(std::initializer_list{1,2}),C(std::string("bar")))) // X x1; - // x({x1}); // no matching constructor + // x({x1}); // calls copy constructor // } public void testListInitialization_302412c() throws Exception { String code = getAboveComment(); @@ -8859,7 +8859,7 @@ public void testListInitialization_302412c() throws Exception { bh.assertProblem("f({ 'a', 'b' })", 1); bh.assertNonProblem("h({", 1); bh.assertNonProblem("i({ { 1, 2 }, {", 1); - bh.assertProblem("x({x1})", 1); + bh.assertNonProblem("x({x1})", 1); } // namespace std { @@ -9052,6 +9052,17 @@ public void testListInitializer_495227() throws Exception { assertEquals(2, ((ICPPConstructor) binding).getType().getParameterTypes().length); } + // struct C { + // C(int); + // }; + // void foo() { + // const C a; + // C b{a}; + // } + public void testListInit_CopyConstructor_559318() throws Exception { + parseAndCheckImplicitNameBindings(); + } + // struct S { // int a; // float b; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java index 91c53594dc9..ba2e96f9db6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java @@ -540,7 +540,7 @@ private static final Cost checkStandardConversionSequence(IType source, IType ta return cost; } - // [over.match.list] Initialization by list-initialization + // [dcl.list.init][over.match.list] Initialization by list-initialization static Cost listInitializationOfClass(EvalInitList arg, ICPPClassType t, boolean isDirect, boolean deferUDC) throws DOMException { if (deferUDC) { @@ -549,6 +549,27 @@ static Cost listInitializationOfClass(EvalInitList arg, ICPPClassType t, boolean return c; } + // [dcl.init.list] 3.2 if T is a class and the initializer list has a single element of type U + // where U is T or a subclass of T, the object is initialised from that element + if (arg.getClauses().length == 1) { + IType singleArgType = arg.getClauses()[0].getType(); + singleArgType = getNestedType(singleArgType, CVTYPE | TDEF); + if (singleArgType instanceof ICPPClassType) { + ICPPClassType argType = (ICPPClassType) singleArgType; + // [over.ics.list] the cost is that of converting the single value to the + // parameter type + int depth = SemanticUtil.calculateInheritanceDepth(singleArgType, t); + if (depth == 0) { + return new Cost(argType, t, Rank.IDENTITY); + } + if (depth > 0) { + Cost c = new Cost(argType, t, Rank.CONVERSION); + c.setInheritanceDistance(depth); + return c; + } + } + } + // p1: When objects of non-aggregate class type are list-initialized, // [...] overload resoution selects the constructor in two phases: