diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/CompositeValue.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/CompositeValue.java index 362920b8ad3..d3435a01260 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/CompositeValue.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/CompositeValue.java @@ -16,6 +16,7 @@ import java.util.TreeSet; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ast.ASTTypeUtil; +import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory; import org.eclipse.cdt.core.dom.ast.IArrayType; import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.ICompositeType; @@ -147,13 +148,24 @@ public final class CompositeValue implements IValue { ICPPEvaluation[] values = new ICPPEvaluation[fields.length]; ICPPEvaluation[] clauses = initList.getClauses(); for (int i = 0; i < fields.length; i++) { - if (i == clauses.length) - break; IField field = fields[i]; - ICPPEvaluation eval = clauses[i]; IType fieldType = field.getType(); - IValue value = getValue(fieldType, eval); - values[i] = new EvalFixed(fieldType, eval.getValueCategory(), value); + IValue value; + ValueCategory valueCategory; + if (i < clauses.length) { + ICPPEvaluation eval = clauses[i]; + value = getValue(fieldType, eval); + valueCategory = eval.getValueCategory(); + } else { + // (dcl.init.aggr-7) from brace-or-equal-initializer or from {} + value = field.getInitialValue(); + // Writing IntegralValue.UNKNOWN to PDOM stores null, convert it back + if (value == null || value == IntegralValue.UNKNOWN) { + value = IntegralValue.create(0); + } + valueCategory = ValueCategory.PRVALUE; + } + values[i] = new EvalFixed(fieldType, valueCategory, value); } return new CompositeValue(initList, values); } 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 d32481d3087..0f6eae40b77 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 @@ -99,7 +99,7 @@ class AggregateInitialization { } Cost costWithoutElision = Conversions.checkImplicitConversionSequence(nestedType, initializer.getType(), - initializer.getValueCategory(), UDCMode.ALLOWED, Context.ORDINARY); + initializer.getValueCategory(), UDCMode.ALLOWED, Context.ORDINARY, false); if (costWithoutElision.converts()) { // p3: The elements of the initializer list are taken as initializers for the elements // of the aggregate, in order. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPEvaluation.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPEvaluation.java index c25776b0255..8c6e88e63a3 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPEvaluation.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPEvaluation.java @@ -195,7 +195,7 @@ public abstract class CPPEvaluation implements ICPPEvaluation { ValueCategory valueCategory = argument.getValueCategory(); if (uqType instanceof ICPPClassType) { Cost cost = Conversions.initializationByConversion(valueCategory, type, (ICPPClassType) uqType, - targetType, false, allowContextualConversion); + targetType, false, allowContextualConversion, false); ICPPFunction conversion = cost.getUserDefinedConversion(); if (conversion != null) { if (onlyConstexprConversion && !conversion.isConstexpr()) { @@ -210,7 +210,7 @@ public abstract class CPPEvaluation implements ICPPEvaluation { // Source type is not a class type, or is but a conversion operator wasn't used. // Check for standard conversions. Cost cost = Conversions.checkImplicitConversionSequence(targetType, type, valueCategory, UDCMode.FORBIDDEN, - Context.ORDINARY); + Context.ORDINARY, false); if (!cost.converts()) { return EvalFixed.INCOMPLETE; } else if (cost.getRank() == Rank.CONVERSION) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index b804175003e..b6d65d2112d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -3169,7 +3169,14 @@ public class CPPSemantics { if (potentialCosts != null) { for (FunctionCost fnCost : potentialCosts) { - if (!fnCost.mustBeWorse(bestFnCost) && fnCost.performUDC()) { + if (!fnCost.mustBeWorse(bestFnCost) && fnCost.performUDC(data.fNoNarrowing)) { + if (data.fNoNarrowing) { + for (int i = 0; i < fnCost.getLength(); ++i) { + if (fnCost.getCost(i).isNarrowingConversion()) { + continue; + } + } + } int cmp = fnCost.compareTo(tu, bestFnCost, data.getFunctionArgumentCount()); if (cmp < 0) { bestFnCost = fnCost; @@ -3473,7 +3480,7 @@ public class CPPSemantics { Context context = ftype.hasRefQualifier() ? Context.IMPLICIT_OBJECT_FOR_METHOD_WITH_REF_QUALIFIER : Context.IMPLICIT_OBJECT_FOR_METHOD_WITHOUT_REF_QUALIFIER; cost = Conversions.checkImplicitConversionSequence(implicitParameterType, impliedObjectType, - impliedObjectValueCategory, UDCMode.FORBIDDEN, context); + impliedObjectValueCategory, UDCMode.FORBIDDEN, context, data.fNoNarrowing); if (cost.converts()) { cost.setImpliedObject(); } else { @@ -3530,7 +3537,9 @@ public class CPPSemantics { } } } - cost = Conversions.checkImplicitConversionSequence(paramType, argType, argValueCategory, udc, ctx); + cost = Conversions.checkImplicitConversionSequence(paramType, argType, argValueCategory, udc, ctx, + data.fNoNarrowing); + // TODO: see if isNarrowingConversion() is re-checked while performing UDC again later if (data.fNoNarrowing && cost.isNarrowingConversion()) { cost = Cost.NO_CONVERSION; } @@ -4118,10 +4127,16 @@ public class CPPSemantics { if (initializer == null) { IASTDeclSpecifier declSpec = ((IASTSimpleDeclaration) parent).getDeclSpecifier(); parent = parent.getParent(); - if (parent instanceof IASTCompositeTypeSpecifier + // (c++11:class.base.init 12.6.2-8) [..no initializer..] + // if the entity is an anonymous union or a variant member, no initialization is performed + // otherwise the entity is default-initialized + // (c++11:dcl.init 8.5-7) + // if T is a (possibly cv-qualified) class type .. the default constructor for T is called + if ((parent instanceof IASTCompositeTypeSpecifier compositeType + && compositeType.getKey() == ICompositeType.k_union) || declSpec.getStorageClass() == IASTDeclSpecifier.sc_extern) { - // No initialization is performed for class members and extern declarations - // without an initializer. + // No initialization is performed for class members which are of union type, + // and for extern declarations without an initializer. return null; } } @@ -4182,6 +4197,20 @@ public class CPPSemantics { return null; } + public static IBinding findConstructorForDirectListInitialization(ICPPClassType type, EvalInitList eval, + IASTNode typeId) throws DOMException { + Cost c = Conversions.listInitializationSequence(eval, type, UDCMode.ALLOWED, true); + if (c.converts()) { + ICPPFunction f = c.getUserDefinedConversion(); + if (f instanceof ICPPConstructor) { + return f; + } + } else { + return new ProblemBinding(null, typeId, ISemanticProblem.BINDING_NOT_FOUND, type.getConstructors()); + } + return null; + } + private static IBinding findImplicitlyCalledConstructor(ICPPClassType type, IASTInitializer initializer, IASTNode typeId) { pushLookupPoint(typeId); @@ -4207,10 +4236,10 @@ public class CPPSemantics { } Cost c; if (calculateInheritanceDepth(sourceType, type) >= 0) { - c = Conversions.copyInitializationOfClass(isLValue, sourceType, type, false); + c = Conversions.copyInitializationOfClass(isLValue, sourceType, type, false, false); } else { c = Conversions.checkImplicitConversionSequence(type, sourceType, isLValue, UDCMode.ALLOWED, - Context.ORDINARY); + Context.ORDINARY, false); } if (c.converts()) { ICPPFunction f = c.getUserDefinedConversion(); @@ -4225,7 +4254,7 @@ public class CPPSemantics { } else if (initializer instanceof ICPPASTInitializerList) { // List initialization. ICPPEvaluation eval = ((ICPPASTInitializerClause) initializer).getEvaluation(); - if (eval instanceof EvalInitList) { + if (eval instanceof EvalInitList evalInitList) { if (CPPTemplates.isDependentType(eval.getType())) { ICPPEvaluation[] clauses = ((EvalInitList) eval).getClauses(); IType[] tmp = new IType[clauses.length]; @@ -4235,14 +4264,9 @@ public class CPPSemantics { setTargetedFunctionsToUnknown(tmp); return CPPDeferredFunction.createForCandidates(type.getConstructors()); } - Cost c = Conversions.listInitializationSequence((EvalInitList) eval, type, UDCMode.ALLOWED, true); - if (c.converts()) { - ICPPFunction f = c.getUserDefinedConversion(); - if (f instanceof ICPPConstructor) - return f; - } else { - return new ProblemBinding(null, typeId, ISemanticProblem.BINDING_NOT_FOUND, - type.getConstructors()); + IBinding b = findConstructorForDirectListInitialization(type, evalInitList, typeId); + if (b != null) { + return b; } } } else if (initializer instanceof ICPPASTConstructorInitializer) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java index 78d43af320a..3f08893f8ba 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java @@ -2983,7 +2983,8 @@ public class CPPTemplates { } } - Cost cost = Conversions.checkImplicitConversionSequence(p, a, LVALUE, UDCMode.FORBIDDEN, Context.ORDINARY); + Cost cost = Conversions.checkImplicitConversionSequence(p, a, LVALUE, UDCMode.FORBIDDEN, Context.ORDINARY, + false); if (cost == null || !cost.converts()) { ICPPEvaluation eval = arg.getNonTypeEvaluation(); ICPPEvaluation newEval = CPPEvaluation.maybeApplyConversion(eval, p, false, true); 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..f49459ecaa8 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 @@ -99,7 +99,7 @@ public class Conversions { * @throws DOMException */ public static Cost checkImplicitConversionSequence(IType target, IType exprType, ValueCategory valueCat, - UDCMode udc, Context ctx) throws DOMException { + UDCMode udc, Context ctx, boolean noNarrowing) throws DOMException { final boolean isImpliedObject = ctx == Context.IMPLICIT_OBJECT_FOR_METHOD_WITHOUT_REF_QUALIFIER || ctx == Context.IMPLICIT_OBJECT_FOR_METHOD_WITH_REF_QUALIFIER; if (isImpliedObject) @@ -211,7 +211,7 @@ public class Conversions { // 13.3.3.1.7 no temporary object when converting the implicit object parameter if (!isImpliedObject && ctx != Context.REQUIRE_DIRECT_BINDING) { - Cost cost = nonReferenceConversion(valueCat, cv2T2, T1, udc); + Cost cost = nonReferenceConversion(valueCat, cv2T2, T1, udc, noNarrowing); if (cost.converts()) { cost.setReferenceBinding(refBindingType); } @@ -232,7 +232,7 @@ public class Conversions { } // Non-reference binding - return nonReferenceConversion(valueCat, exprType, T1, udc); + return nonReferenceConversion(valueCat, exprType, T1, udc, noNarrowing); } /** @@ -297,8 +297,8 @@ public class Conversions { /** * 8.5-16 */ - private static Cost nonReferenceConversion(ValueCategory valueCat, IType source, IType target, UDCMode udc) - throws DOMException { + private static Cost nonReferenceConversion(ValueCategory valueCat, IType source, IType target, UDCMode udc, + boolean noNarrowing) throws DOMException { if (source instanceof InitializerListType) { return listInitializationSequence(((InitializerListType) source).getEvaluation(), target, udc, false); } @@ -321,7 +321,8 @@ public class Conversions { if (udc == UDCMode.FORBIDDEN) return Cost.NO_CONVERSION; - return copyInitializationOfClass(valueCat, source, (ICPPClassType) uqTarget, udc == UDCMode.DEFER); + return copyInitializationOfClass(valueCat, source, (ICPPClassType) uqTarget, udc == UDCMode.DEFER, + noNarrowing); } if (uqSource instanceof ICPPClassType) { @@ -329,7 +330,7 @@ public class Conversions { return Cost.NO_CONVERSION; return initializationByConversion(valueCat, source, (ICPPClassType) uqSource, target, udc == UDCMode.DEFER, - false); + false, noNarrowing); } return checkStandardConversionSequence(uqSource, target); @@ -352,7 +353,7 @@ public class Conversions { Cost worstCost = new Cost(arg.getType(), target, Rank.IDENTITY); for (ICPPEvaluation clause : arg.getClauses()) { Cost cost = checkImplicitConversionSequence(listType, clause.getType(), clause.getValueCategory(), - UDCMode.ALLOWED, Context.ORDINARY); + UDCMode.ALLOWED, Context.ORDINARY, false); if (!cost.converts()) return cost; if (cost.isNarrowingConversion()) { @@ -389,7 +390,7 @@ public class Conversions { final ICPPEvaluation firstArg = args[0]; if (!firstArg.isInitializerList()) { Cost cost = checkImplicitConversionSequence(target, firstArg.getType(), firstArg.getValueCategory(), - udc, Context.ORDINARY); + udc, Context.ORDINARY, false); if (cost.isNarrowingConversion()) { return Cost.NO_CONVERSION; } @@ -614,24 +615,7 @@ public class Conversions { data.fNoNarrowing = true; // 13.3.3.1.4 - ICPPConstructor[] filteredConstructors = constructors; - if (expandedArgs.length == 1) { - filteredConstructors = new ICPPConstructor[constructors.length]; - int j = 0; - for (ICPPConstructor ctor : constructors) { - if (ctor.getRequiredArgumentCount() < 2) { - IType[] ptypes = ctor.getType().getParameterTypes(); - if (ptypes.length > 0) { - IType ptype = getNestedType(ptypes[0], TDEF | REF | CVTYPE); - if (!t.isSameType(ptype)) { - filteredConstructors[j++] = ctor; - } - } - } - } - } - - final IBinding result = CPPSemantics.resolveFunction(data, filteredConstructors, true, false); + final IBinding result = CPPSemantics.resolveFunction(data, constructors, true, false); final Cost c; if (result instanceof ICPPMethod) { if (!isDirect && ((ICPPMethod) result).isExplicit()) { @@ -658,8 +642,8 @@ public class Conversions { /** * 13.3.1.4 Copy-initialization of class by user-defined conversion [over.match.copy] */ - static final Cost copyInitializationOfClass(ValueCategory valueCat, IType source, ICPPClassType t, boolean deferUDC) - throws DOMException { + static final Cost copyInitializationOfClass(ValueCategory valueCat, IType source, ICPPClassType t, boolean deferUDC, + boolean noNarrowing) throws DOMException { if (deferUDC) { Cost c = new Cost(source, t, Rank.USER_DEFINED_CONVERSION); c.setDeferredUDC(DeferredUDC.COPY_INIT_OF_CLASS); @@ -698,8 +682,14 @@ public class Conversions { if (ctor.getRequiredArgumentCount() > 1) continue; - c1 = new FunctionCost(ctor, checkImplicitConversionSequence(ptype, source, valueCat, - UDCMode.FORBIDDEN, Context.ORDINARY)); + Cost cost = checkImplicitConversionSequence(ptype, source, valueCat, UDCMode.FORBIDDEN, + Context.ORDINARY, noNarrowing); + + if (noNarrowing && cost.isNarrowingConversion()) { + cost = Cost.NO_CONVERSION; + } + + c1 = new FunctionCost(ctor, cost); } int cmp = c1.compareTo(null, cost1, 1); if (cmp <= 0) { @@ -761,7 +751,7 @@ public class Conversions { * 13.3.1.5 Initialization by conversion function [over.match.conv] */ static Cost initializationByConversion(ValueCategory valueCat, IType source, ICPPClassType uqSource, IType target, - boolean deferUDC, boolean allowExplicitConversion) throws DOMException { + boolean deferUDC, boolean allowExplicitConversion, boolean noNarrowing) throws DOMException { if (deferUDC) { Cost c = new Cost(source, target, Rank.USER_DEFINED_CONVERSION); c.setDeferredUDC(DeferredUDC.INIT_BY_CONVERSION); @@ -783,7 +773,7 @@ public class Conversions { final IType returnType = functionType.getReturnType(); IType uqReturnType = getNestedType(returnType, TDEF | ALLCVQ); Cost c2 = checkImplicitConversionSequence(target, uqReturnType, - valueCategoryFromReturnType(uqReturnType), UDCMode.FORBIDDEN, Context.ORDINARY); + valueCategoryFromReturnType(uqReturnType), UDCMode.FORBIDDEN, Context.ORDINARY, noNarrowing); if (c2.converts()) { if (isExplicitConversion && c2.getRank() != Rank.IDENTITY) continue; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalConditional.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalConditional.java index 49cc3df4639..b0e471ae08a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalConditional.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalConditional.java @@ -306,7 +306,7 @@ public class EvalConditional extends CPPDependentEvaluation { if (vcat2.isGLValue()) { IType target = new CPPReferenceType(t2, vcat2 == XVALUE); Cost c = Conversions.checkImplicitConversionSequence(target, t1, vcat1, UDCMode.ALLOWED, - Context.REQUIRE_DIRECT_BINDING); + Context.REQUIRE_DIRECT_BINDING, false); if (c.converts()) { fType = t2; fValueCategory = vcat2; @@ -333,7 +333,8 @@ public class EvalConditional extends CPPDependentEvaluation { if (vcat2 != PRVALUE) { t2 = Conversions.lvalue_to_rvalue(t2, false); } - Cost c = Conversions.checkImplicitConversionSequence(t2, t1, vcat1, UDCMode.ALLOWED, Context.ORDINARY); + Cost c = Conversions.checkImplicitConversionSequence(t2, t1, vcat1, UDCMode.ALLOWED, Context.ORDINARY, + false); if (c.converts()) { fType = t2; fValueCategory = PRVALUE; 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 09533b43e4a..2ddd4282b44 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 @@ -35,7 +35,6 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction; -import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.core.parser.util.ArrayUtil; @@ -234,7 +233,9 @@ public class EvalTypeId extends CPPDependentEvaluation { } private boolean computeIsConstantExpression() { - if (getConstructor() == null && fArguments.length == 1) { + ICPPFunction constructor = getConstructor(); + + if (constructor == null && fArguments.length == 1) { // maybe EvalTypeID represents a conversion ICPPEvaluation conversionEval = maybeApplyConversion(fArguments[0], fInputType, false, false); if (isEquivalentTo(conversionEval)) { @@ -244,9 +245,13 @@ public class EvalTypeId extends CPPDependentEvaluation { if (!conversionEval.isConstantExpression()) return false; + } else if (constructor == AGGREGATE_INITIALIZATION) { + // A literal type is one for which it might be possible to create an object within a constant expression. + // See also CPPImplicitConstructor.isConstExpr() + return getInputType() instanceof ICPPClassType classType && TypeTraits.isLiteralClass(classType); } - return !fRepresentsNewExpression && areAllConstantExpressions(fArguments) - && isNullOrConstexprFunc(getConstructor()); + + return !fRepresentsNewExpression && areAllConstantExpressions(fArguments) && isNullOrConstexprFunc(constructor); } @Override @@ -285,38 +290,35 @@ public class EvalTypeId extends CPPDependentEvaluation { return null; IType simplifiedType = SemanticUtil.getNestedType(fInputType, TDEF | CVTYPE); - if (simplifiedType instanceof ICPPClassType) { - ICPPClassType classType = (ICPPClassType) simplifiedType; - ICPPEvaluation[] arguments = fArguments; - ICPPConstructor[] constructors = classType.getConstructors(); - if (fUsesBracedInitList && arguments.length > 0) { - // List-initialization of a class (dcl.init.list-3). - // e.g. A{1,2} - ICPPConstructor[] ctors = getInitializerListConstructors(constructors); - if (ctors.length != 0) { - constructors = ctors; - arguments = new EvalInitList[] { new EvalInitList(arguments, getTemplateDefinition()) }; - } - } else if (arguments.length == 1 && arguments[0] instanceof EvalInitList && !fUsesBracedInitList) { - // List-initialization of a class (dcl.init.list-3). - // e.g. A({1,2}) - if (TypeTraits.isAggregateClass(classType)) { - // Pretend that aggregate initialization is calling the default constructor. - return findDefaultConstructor(classType, constructors); - } - if (((EvalInitList) arguments[0]).getClauses().length == 0) { - ICPPMethod ctor = findDefaultConstructor(classType, constructors); - if (ctor != null) - return ctor; - } - ICPPConstructor[] ctors = getInitializerListConstructors(constructors); - if (ctors.length != 0) { - constructors = ctors; - } else { - arguments = ((EvalInitList) arguments[0]).getClauses(); + if (simplifiedType instanceof ICPPClassType classType) { + if (fUsesBracedInitList) { + // (dcl.init.list) + EvalInitList evalInitList = new EvalInitList(fArguments, getTemplateDefinition()); + + try { + // List-initialization of a class (dcl.init.list-3). + // e.g. A{1,2} + IBinding binding = CPPSemantics.findConstructorForDirectListInitialization(classType, evalInitList, + null); + if (binding instanceof ICPPConstructor constructor) { + return constructor; + } else if (binding instanceof IProblemBinding) { + return new CPPFunction.CPPFunctionProblem(null, ISemanticProblem.BINDING_NOT_FOUND, + classType.getNameCharArray()); + } else if (TypeTraits.isAggregateClass(classType)) { + // If Conversions.listInitializationSequence() did not returned problem binding, + // this is a list-initialization of aggregate class, and there is no constructor. + return AGGREGATE_INITIALIZATION; + } + } catch (DOMException e) { + CCorePlugin.log(e); } + + return null; } + ICPPEvaluation[] arguments = fArguments; + ICPPConstructor[] constructors = classType.getConstructors(); LookupData data = new LookupData(classType.getNameCharArray(), null, CPPSemantics.getCurrentLookupPoint()); data.foundItems = constructors; data.setFunctionArguments(false, arguments); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionCost.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionCost.java index d77b19e72fd..578f76c0470 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionCost.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionCost.java @@ -98,7 +98,7 @@ class FunctionCost { return false; } - public boolean performUDC() throws DOMException { + public boolean performUDC(boolean noNarrowing) throws DOMException { for (int i = 0; i < fCosts.length; i++) { Cost cost = fCosts[i]; Cost udcCost = null; @@ -107,12 +107,12 @@ class FunctionCost { continue; case COPY_INIT_OF_CLASS: udcCost = Conversions.copyInitializationOfClass(fValueCategories[i], cost.source, - (ICPPClassType) cost.target, false); + (ICPPClassType) cost.target, false, noNarrowing); break; case INIT_BY_CONVERSION: IType uqSource = getNestedType(cost.source, TDEF | REF | CVTYPE); udcCost = Conversions.initializationByConversion(fValueCategories[i], cost.source, - (ICPPClassType) uqSource, cost.target, false, allowsContextualBooleanConversion()); + (ICPPClassType) uqSource, cost.target, false, allowsContextualBooleanConversion(), noNarrowing); break; case LIST_INIT_OF_CLASS: udcCost = Conversions.listInitializationOfClass(((InitializerListType) cost.source).getEvaluation(), @@ -126,6 +126,7 @@ class FunctionCost { return false; } fCosts[i] = udcCost; + if (!udcCost.converts()) { return false; } diff --git a/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF b/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF index cb839628c20..89440b66807 100644 --- a/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF +++ b/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.cdt.ui; singleton:=true -Bundle-Version: 8.1.200.qualifier +Bundle-Version: 8.1.300.qualifier Bundle-Activator: org.eclipse.cdt.ui.CUIPlugin Bundle-Vendor: %providerName Bundle-Localization: plugin @@ -104,7 +104,7 @@ Export-Package: org.eclipse.cdt.internal.corext;x-internal:=true, org.eclipse.cdt.ui.wizards.conversion, org.eclipse.cdt.utils.ui.controls Import-Package: org.apache.commons.io;version="[2.8.0,3.0.0)" -Require-Bundle: org.eclipse.cdt.core;bundle-version="[8.3.0,9.0.0)", +Require-Bundle: org.eclipse.cdt.core;bundle-version="[8.4.0,9.0.0)", org.eclipse.compare;bundle-version="[3.8.500,4.0.0)", org.eclipse.core.expressions;bundle-version="[3.8.200,4.0.0)", org.eclipse.core.filesystem;bundle-version="[1.9.500,2.0.0)", diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ParameterGuesser.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ParameterGuesser.java index fbf2a093db9..5ae96c95e1c 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ParameterGuesser.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/contentassist/ParameterGuesser.java @@ -180,7 +180,7 @@ public class ParameterGuesser { private boolean isImplicitlyConvertible(IType orginType, IType candidateType) { try { Cost cost = Conversions.checkImplicitConversionSequence(orginType, candidateType, ValueCategory.LVALUE, - UDCMode.ALLOWED, Context.ORDINARY); + UDCMode.ALLOWED, Context.ORDINARY, false); if (cost.converts()) return true; } catch (DOMException e) {