From d42c60b651210a25813c11e24dac92f3cfc1c555 Mon Sep 17 00:00:00 2001 From: Hannes Vogt Date: Thu, 21 Feb 2019 23:29:38 +0100 Subject: [PATCH] Bug 543038 - Addition to brace elision for aggregate init - getNestedType for typedefs - check aggregate initialization in EvalTypeID Change-Id: I04ab2088c85373007312f7a419eb508ab53f69c8 Signed-off-by: Hannes Vogt --- .../core/parser/tests/ast2/AST2CPPTests.java | 32 +++++++++++++------ .../semantics/AggregateInitialization.java | 11 ++++--- .../dom/parser/cpp/semantics/EvalTypeId.java | 15 +++++---- .../dom/parser/cpp/semantics/TypeTraits.java | 4 +++ 4 files changed, 41 insertions(+), 21 deletions(-) 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 93aeab5dc0a..90d4b2a7b7e 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 @@ -12885,8 +12885,8 @@ public class AST2CPPTests extends AST2CPPTestBase { // } 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("array{{1,2}}", 5, IProblemBinding.class); + bh.assertImplicitName("array{1,2}", 5, IProblemBinding.class); bh.assertImplicitName("a0", 2, IProblemBinding.class); bh.assertProblem("foo({1,2})", 3); bh.assertProblem("foo({{1,2}})", 3); @@ -12918,14 +12918,8 @@ public class AST2CPPTests extends AST2CPPTestBase { // } 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, ICPPConstructor.class); bh.assertImplicitName("level1{1,2};", 6, IProblemBinding.class); bh.assertProblem("foo({{{1,2,3}}}", 3); } @@ -12989,4 +12983,24 @@ public class AST2CPPTests extends AST2CPPTestBase { bh.assertNonProblem("foo({{1,2,3,{1,2,3}}});", 3); bh.assertProblem("foo({{1,2,{1,2,3}}});", 3); } + + // template + // struct trait { + // using type = T[D]; + // }; + // + // template + // struct array { + // typename trait::type data; + // }; + // + // void foo(array) { + // } + // + // int main() { + // foo({1}); + // } + public void testBraceElisionForAggregateInit6_typedef_543038() throws Exception { + parseAndCheckBindings(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/AggregateInitialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/AggregateInitialization.java index 68401ab2834..e3afebd2e6b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/AggregateInitialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/AggregateInitialization.java @@ -60,17 +60,18 @@ class AggregateInitialization { * else recurses into the subaggregate. */ private Cost checkElement(IType type, IValue initialValue, Cost worstCost) throws DOMException { + IType nestedType = SemanticUtil.getNestedType(type, SemanticUtil.TDEF); 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); + return checkInitializationFromDefaultMemberInitializer(nestedType, initialValue, worstCost); + worstCost = new Cost(fInitializers[fIndex].getType(), nestedType, Rank.IDENTITY); - if (fInitializers[fIndex].isInitializerList() || !isAggregate(type)) { // no braces are elided + if (fInitializers[fIndex].isInitializerList() || !isAggregate(nestedType)) { // 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(), + Cost cost = Conversions.checkImplicitConversionSequence(nestedType, initializer.getType(), initializer.getValueCategory(), UDCMode.ALLOWED, Context.ORDINARY); if (!cost.converts()) { return cost; @@ -84,7 +85,7 @@ class AggregateInitialization { worstCost = cost; } } else { // braces are elided: need to check on subaggregates - Cost cost = checkInitializationOfElements(type, worstCost); + Cost cost = checkInitializationOfElements(nestedType, worstCost); if (!cost.converts()) return cost; if (cost.compareTo(worstCost) > 0) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java index 63837ab46f9..73b870c5fda 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalTypeId.java @@ -25,6 +25,7 @@ import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IProblemBinding; +import org.eclipse.cdt.core.dom.ast.ISemanticProblem; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType; @@ -299,9 +300,14 @@ public class EvalTypeId extends CPPDependentEvaluation { if (binding instanceof ICPPFunction) { return (ICPPFunction) binding; } - // TODO check aggregate initialization if (fUsesBracedInitList && allConstructorsAreCompilerGenerated(constructors)) { - return AGGREGATE_INITIALIZATION; + Cost cost = AggregateInitialization.check(classType, + new EvalInitList(arguments, getTemplateDefinition())); + if (cost.converts()) + return AGGREGATE_INITIALIZATION; + else + return new CPPFunction.CPPFunctionProblem(null, ISemanticProblem.BINDING_NOT_FOUND, + classType.getNameCharArray()); } if (binding instanceof IProblemBinding && !(binding instanceof ICPPFunction)) return new CPPFunction.CPPFunctionProblem(null, ((IProblemBinding) binding).getID(), @@ -309,11 +315,6 @@ public class EvalTypeId extends CPPDependentEvaluation { } catch (DOMException e) { CCorePlugin.log(e); } - - // TODO check aggregate initialization - if (fUsesBracedInitList && allConstructorsAreCompilerGenerated(constructors)) { - return AGGREGATE_INITIALIZATION; - } } return null; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TypeTraits.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TypeTraits.java index 71af56c0d23..cbba16a0c70 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TypeTraits.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TypeTraits.java @@ -45,6 +45,7 @@ import org.eclipse.cdt.internal.core.dom.parser.ArithmeticConversion; import org.eclipse.cdt.internal.core.dom.parser.IntegralValue; import org.eclipse.cdt.internal.core.dom.parser.ProblemType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClosureType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPImplicitConstructor; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUnaryTypeTransformation; @@ -267,6 +268,9 @@ public class TypeTraits { * no base classes (Clause 10), and no virtual functions (10.3). */ public static boolean isAggregateClass(ICPPClassType classType) { + // 8.1.5.1 p.2 (N4659): The closure type is not an aggregate type. + if (classType instanceof CPPClosureType) + return false; if (classType.getBases().length > 0) return false; ICPPMethod[] methods = classType.getDeclaredMethods();