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

Amend list-initialization handling of class or aggregate

This commit is contained in:
Igor V. Kovalenko 2023-10-07 23:45:38 +03:00 committed by Jonah Graham
parent ae3a0adb81
commit 84322c30f4
11 changed files with 131 additions and 100 deletions

View file

@ -16,6 +16,7 @@ import java.util.TreeSet;
import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.ASTTypeUtil; 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.IArrayType;
import org.eclipse.cdt.core.dom.ast.IBinding; import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.ICompositeType; 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[] values = new ICPPEvaluation[fields.length];
ICPPEvaluation[] clauses = initList.getClauses(); ICPPEvaluation[] clauses = initList.getClauses();
for (int i = 0; i < fields.length; i++) { for (int i = 0; i < fields.length; i++) {
if (i == clauses.length)
break;
IField field = fields[i]; IField field = fields[i];
ICPPEvaluation eval = clauses[i];
IType fieldType = field.getType(); IType fieldType = field.getType();
IValue value = getValue(fieldType, eval); IValue value;
values[i] = new EvalFixed(fieldType, eval.getValueCategory(), 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); return new CompositeValue(initList, values);
} }

View file

@ -99,7 +99,7 @@ class AggregateInitialization {
} }
Cost costWithoutElision = Conversions.checkImplicitConversionSequence(nestedType, initializer.getType(), Cost costWithoutElision = Conversions.checkImplicitConversionSequence(nestedType, initializer.getType(),
initializer.getValueCategory(), UDCMode.ALLOWED, Context.ORDINARY); initializer.getValueCategory(), UDCMode.ALLOWED, Context.ORDINARY, false);
if (costWithoutElision.converts()) { if (costWithoutElision.converts()) {
// p3: The elements of the initializer list are taken as initializers for the elements // p3: The elements of the initializer list are taken as initializers for the elements
// of the aggregate, in order. // of the aggregate, in order.

View file

@ -195,7 +195,7 @@ public abstract class CPPEvaluation implements ICPPEvaluation {
ValueCategory valueCategory = argument.getValueCategory(); ValueCategory valueCategory = argument.getValueCategory();
if (uqType instanceof ICPPClassType) { if (uqType instanceof ICPPClassType) {
Cost cost = Conversions.initializationByConversion(valueCategory, type, (ICPPClassType) uqType, Cost cost = Conversions.initializationByConversion(valueCategory, type, (ICPPClassType) uqType,
targetType, false, allowContextualConversion); targetType, false, allowContextualConversion, false);
ICPPFunction conversion = cost.getUserDefinedConversion(); ICPPFunction conversion = cost.getUserDefinedConversion();
if (conversion != null) { if (conversion != null) {
if (onlyConstexprConversion && !conversion.isConstexpr()) { 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. // Source type is not a class type, or is but a conversion operator wasn't used.
// Check for standard conversions. // Check for standard conversions.
Cost cost = Conversions.checkImplicitConversionSequence(targetType, type, valueCategory, UDCMode.FORBIDDEN, Cost cost = Conversions.checkImplicitConversionSequence(targetType, type, valueCategory, UDCMode.FORBIDDEN,
Context.ORDINARY); Context.ORDINARY, false);
if (!cost.converts()) { if (!cost.converts()) {
return EvalFixed.INCOMPLETE; return EvalFixed.INCOMPLETE;
} else if (cost.getRank() == Rank.CONVERSION) { } else if (cost.getRank() == Rank.CONVERSION) {

View file

@ -3169,7 +3169,14 @@ public class CPPSemantics {
if (potentialCosts != null) { if (potentialCosts != null) {
for (FunctionCost fnCost : potentialCosts) { 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()); int cmp = fnCost.compareTo(tu, bestFnCost, data.getFunctionArgumentCount());
if (cmp < 0) { if (cmp < 0) {
bestFnCost = fnCost; bestFnCost = fnCost;
@ -3473,7 +3480,7 @@ public class CPPSemantics {
Context context = ftype.hasRefQualifier() ? Context.IMPLICIT_OBJECT_FOR_METHOD_WITH_REF_QUALIFIER Context context = ftype.hasRefQualifier() ? Context.IMPLICIT_OBJECT_FOR_METHOD_WITH_REF_QUALIFIER
: Context.IMPLICIT_OBJECT_FOR_METHOD_WITHOUT_REF_QUALIFIER; : Context.IMPLICIT_OBJECT_FOR_METHOD_WITHOUT_REF_QUALIFIER;
cost = Conversions.checkImplicitConversionSequence(implicitParameterType, impliedObjectType, cost = Conversions.checkImplicitConversionSequence(implicitParameterType, impliedObjectType,
impliedObjectValueCategory, UDCMode.FORBIDDEN, context); impliedObjectValueCategory, UDCMode.FORBIDDEN, context, data.fNoNarrowing);
if (cost.converts()) { if (cost.converts()) {
cost.setImpliedObject(); cost.setImpliedObject();
} else { } 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()) { if (data.fNoNarrowing && cost.isNarrowingConversion()) {
cost = Cost.NO_CONVERSION; cost = Cost.NO_CONVERSION;
} }
@ -4118,10 +4127,16 @@ public class CPPSemantics {
if (initializer == null) { if (initializer == null) {
IASTDeclSpecifier declSpec = ((IASTSimpleDeclaration) parent).getDeclSpecifier(); IASTDeclSpecifier declSpec = ((IASTSimpleDeclaration) parent).getDeclSpecifier();
parent = parent.getParent(); 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) { || declSpec.getStorageClass() == IASTDeclSpecifier.sc_extern) {
// No initialization is performed for class members and extern declarations // No initialization is performed for class members which are of union type,
// without an initializer. // and for extern declarations without an initializer.
return null; return null;
} }
} }
@ -4182,6 +4197,20 @@ public class CPPSemantics {
return null; 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, private static IBinding findImplicitlyCalledConstructor(ICPPClassType type, IASTInitializer initializer,
IASTNode typeId) { IASTNode typeId) {
pushLookupPoint(typeId); pushLookupPoint(typeId);
@ -4207,10 +4236,10 @@ public class CPPSemantics {
} }
Cost c; Cost c;
if (calculateInheritanceDepth(sourceType, type) >= 0) { if (calculateInheritanceDepth(sourceType, type) >= 0) {
c = Conversions.copyInitializationOfClass(isLValue, sourceType, type, false); c = Conversions.copyInitializationOfClass(isLValue, sourceType, type, false, false);
} else { } else {
c = Conversions.checkImplicitConversionSequence(type, sourceType, isLValue, UDCMode.ALLOWED, c = Conversions.checkImplicitConversionSequence(type, sourceType, isLValue, UDCMode.ALLOWED,
Context.ORDINARY); Context.ORDINARY, false);
} }
if (c.converts()) { if (c.converts()) {
ICPPFunction f = c.getUserDefinedConversion(); ICPPFunction f = c.getUserDefinedConversion();
@ -4225,7 +4254,7 @@ public class CPPSemantics {
} else if (initializer instanceof ICPPASTInitializerList) { } else if (initializer instanceof ICPPASTInitializerList) {
// List initialization. // List initialization.
ICPPEvaluation eval = ((ICPPASTInitializerClause) initializer).getEvaluation(); ICPPEvaluation eval = ((ICPPASTInitializerClause) initializer).getEvaluation();
if (eval instanceof EvalInitList) { if (eval instanceof EvalInitList evalInitList) {
if (CPPTemplates.isDependentType(eval.getType())) { if (CPPTemplates.isDependentType(eval.getType())) {
ICPPEvaluation[] clauses = ((EvalInitList) eval).getClauses(); ICPPEvaluation[] clauses = ((EvalInitList) eval).getClauses();
IType[] tmp = new IType[clauses.length]; IType[] tmp = new IType[clauses.length];
@ -4235,14 +4264,9 @@ public class CPPSemantics {
setTargetedFunctionsToUnknown(tmp); setTargetedFunctionsToUnknown(tmp);
return CPPDeferredFunction.createForCandidates(type.getConstructors()); return CPPDeferredFunction.createForCandidates(type.getConstructors());
} }
Cost c = Conversions.listInitializationSequence((EvalInitList) eval, type, UDCMode.ALLOWED, true); IBinding b = findConstructorForDirectListInitialization(type, evalInitList, typeId);
if (c.converts()) { if (b != null) {
ICPPFunction f = c.getUserDefinedConversion(); return b;
if (f instanceof ICPPConstructor)
return f;
} else {
return new ProblemBinding(null, typeId, ISemanticProblem.BINDING_NOT_FOUND,
type.getConstructors());
} }
} }
} else if (initializer instanceof ICPPASTConstructorInitializer) { } else if (initializer instanceof ICPPASTConstructorInitializer) {

View file

@ -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()) { if (cost == null || !cost.converts()) {
ICPPEvaluation eval = arg.getNonTypeEvaluation(); ICPPEvaluation eval = arg.getNonTypeEvaluation();
ICPPEvaluation newEval = CPPEvaluation.maybeApplyConversion(eval, p, false, true); ICPPEvaluation newEval = CPPEvaluation.maybeApplyConversion(eval, p, false, true);

View file

@ -99,7 +99,7 @@ public class Conversions {
* @throws DOMException * @throws DOMException
*/ */
public static Cost checkImplicitConversionSequence(IType target, IType exprType, ValueCategory valueCat, 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 final boolean isImpliedObject = ctx == Context.IMPLICIT_OBJECT_FOR_METHOD_WITHOUT_REF_QUALIFIER
|| ctx == Context.IMPLICIT_OBJECT_FOR_METHOD_WITH_REF_QUALIFIER; || ctx == Context.IMPLICIT_OBJECT_FOR_METHOD_WITH_REF_QUALIFIER;
if (isImpliedObject) if (isImpliedObject)
@ -211,7 +211,7 @@ public class Conversions {
// 13.3.3.1.7 no temporary object when converting the implicit object parameter // 13.3.3.1.7 no temporary object when converting the implicit object parameter
if (!isImpliedObject && ctx != Context.REQUIRE_DIRECT_BINDING) { 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()) { if (cost.converts()) {
cost.setReferenceBinding(refBindingType); cost.setReferenceBinding(refBindingType);
} }
@ -232,7 +232,7 @@ public class Conversions {
} }
// Non-reference binding // 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 * 8.5-16
*/ */
private static Cost nonReferenceConversion(ValueCategory valueCat, IType source, IType target, UDCMode udc) private static Cost nonReferenceConversion(ValueCategory valueCat, IType source, IType target, UDCMode udc,
throws DOMException { boolean noNarrowing) throws DOMException {
if (source instanceof InitializerListType) { if (source instanceof InitializerListType) {
return listInitializationSequence(((InitializerListType) source).getEvaluation(), target, udc, false); return listInitializationSequence(((InitializerListType) source).getEvaluation(), target, udc, false);
} }
@ -321,7 +321,8 @@ public class Conversions {
if (udc == UDCMode.FORBIDDEN) if (udc == UDCMode.FORBIDDEN)
return Cost.NO_CONVERSION; 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) { if (uqSource instanceof ICPPClassType) {
@ -329,7 +330,7 @@ public class Conversions {
return Cost.NO_CONVERSION; return Cost.NO_CONVERSION;
return initializationByConversion(valueCat, source, (ICPPClassType) uqSource, target, udc == UDCMode.DEFER, return initializationByConversion(valueCat, source, (ICPPClassType) uqSource, target, udc == UDCMode.DEFER,
false); false, noNarrowing);
} }
return checkStandardConversionSequence(uqSource, target); return checkStandardConversionSequence(uqSource, target);
@ -352,7 +353,7 @@ public class Conversions {
Cost worstCost = new Cost(arg.getType(), target, Rank.IDENTITY); Cost worstCost = new Cost(arg.getType(), target, Rank.IDENTITY);
for (ICPPEvaluation clause : arg.getClauses()) { for (ICPPEvaluation clause : arg.getClauses()) {
Cost cost = checkImplicitConversionSequence(listType, clause.getType(), clause.getValueCategory(), Cost cost = checkImplicitConversionSequence(listType, clause.getType(), clause.getValueCategory(),
UDCMode.ALLOWED, Context.ORDINARY); UDCMode.ALLOWED, Context.ORDINARY, false);
if (!cost.converts()) if (!cost.converts())
return cost; return cost;
if (cost.isNarrowingConversion()) { if (cost.isNarrowingConversion()) {
@ -389,7 +390,7 @@ public class Conversions {
final ICPPEvaluation firstArg = args[0]; final ICPPEvaluation firstArg = args[0];
if (!firstArg.isInitializerList()) { if (!firstArg.isInitializerList()) {
Cost cost = checkImplicitConversionSequence(target, firstArg.getType(), firstArg.getValueCategory(), Cost cost = checkImplicitConversionSequence(target, firstArg.getType(), firstArg.getValueCategory(),
udc, Context.ORDINARY); udc, Context.ORDINARY, false);
if (cost.isNarrowingConversion()) { if (cost.isNarrowingConversion()) {
return Cost.NO_CONVERSION; return Cost.NO_CONVERSION;
} }
@ -614,24 +615,7 @@ public class Conversions {
data.fNoNarrowing = true; data.fNoNarrowing = true;
// 13.3.3.1.4 // 13.3.3.1.4
ICPPConstructor[] filteredConstructors = constructors; final IBinding result = CPPSemantics.resolveFunction(data, constructors, true, false);
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 Cost c; final Cost c;
if (result instanceof ICPPMethod) { if (result instanceof ICPPMethod) {
if (!isDirect && ((ICPPMethod) result).isExplicit()) { 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] * 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) static final Cost copyInitializationOfClass(ValueCategory valueCat, IType source, ICPPClassType t, boolean deferUDC,
throws DOMException { boolean noNarrowing) throws DOMException {
if (deferUDC) { if (deferUDC) {
Cost c = new Cost(source, t, Rank.USER_DEFINED_CONVERSION); Cost c = new Cost(source, t, Rank.USER_DEFINED_CONVERSION);
c.setDeferredUDC(DeferredUDC.COPY_INIT_OF_CLASS); c.setDeferredUDC(DeferredUDC.COPY_INIT_OF_CLASS);
@ -698,8 +682,14 @@ public class Conversions {
if (ctor.getRequiredArgumentCount() > 1) if (ctor.getRequiredArgumentCount() > 1)
continue; continue;
c1 = new FunctionCost(ctor, checkImplicitConversionSequence(ptype, source, valueCat, Cost cost = checkImplicitConversionSequence(ptype, source, valueCat, UDCMode.FORBIDDEN,
UDCMode.FORBIDDEN, Context.ORDINARY)); Context.ORDINARY, noNarrowing);
if (noNarrowing && cost.isNarrowingConversion()) {
cost = Cost.NO_CONVERSION;
}
c1 = new FunctionCost(ctor, cost);
} }
int cmp = c1.compareTo(null, cost1, 1); int cmp = c1.compareTo(null, cost1, 1);
if (cmp <= 0) { if (cmp <= 0) {
@ -761,7 +751,7 @@ public class Conversions {
* 13.3.1.5 Initialization by conversion function [over.match.conv] * 13.3.1.5 Initialization by conversion function [over.match.conv]
*/ */
static Cost initializationByConversion(ValueCategory valueCat, IType source, ICPPClassType uqSource, IType target, 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) { if (deferUDC) {
Cost c = new Cost(source, target, Rank.USER_DEFINED_CONVERSION); Cost c = new Cost(source, target, Rank.USER_DEFINED_CONVERSION);
c.setDeferredUDC(DeferredUDC.INIT_BY_CONVERSION); c.setDeferredUDC(DeferredUDC.INIT_BY_CONVERSION);
@ -783,7 +773,7 @@ public class Conversions {
final IType returnType = functionType.getReturnType(); final IType returnType = functionType.getReturnType();
IType uqReturnType = getNestedType(returnType, TDEF | ALLCVQ); IType uqReturnType = getNestedType(returnType, TDEF | ALLCVQ);
Cost c2 = checkImplicitConversionSequence(target, uqReturnType, Cost c2 = checkImplicitConversionSequence(target, uqReturnType,
valueCategoryFromReturnType(uqReturnType), UDCMode.FORBIDDEN, Context.ORDINARY); valueCategoryFromReturnType(uqReturnType), UDCMode.FORBIDDEN, Context.ORDINARY, noNarrowing);
if (c2.converts()) { if (c2.converts()) {
if (isExplicitConversion && c2.getRank() != Rank.IDENTITY) if (isExplicitConversion && c2.getRank() != Rank.IDENTITY)
continue; continue;

View file

@ -306,7 +306,7 @@ public class EvalConditional extends CPPDependentEvaluation {
if (vcat2.isGLValue()) { if (vcat2.isGLValue()) {
IType target = new CPPReferenceType(t2, vcat2 == XVALUE); IType target = new CPPReferenceType(t2, vcat2 == XVALUE);
Cost c = Conversions.checkImplicitConversionSequence(target, t1, vcat1, UDCMode.ALLOWED, Cost c = Conversions.checkImplicitConversionSequence(target, t1, vcat1, UDCMode.ALLOWED,
Context.REQUIRE_DIRECT_BINDING); Context.REQUIRE_DIRECT_BINDING, false);
if (c.converts()) { if (c.converts()) {
fType = t2; fType = t2;
fValueCategory = vcat2; fValueCategory = vcat2;
@ -333,7 +333,8 @@ public class EvalConditional extends CPPDependentEvaluation {
if (vcat2 != PRVALUE) { if (vcat2 != PRVALUE) {
t2 = Conversions.lvalue_to_rvalue(t2, false); 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()) { if (c.converts()) {
fType = t2; fType = t2;
fValueCategory = PRVALUE; fValueCategory = PRVALUE;

View file

@ -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.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor; 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.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.ICPPSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.core.parser.util.ArrayUtil;
@ -234,7 +233,9 @@ public class EvalTypeId extends CPPDependentEvaluation {
} }
private boolean computeIsConstantExpression() { private boolean computeIsConstantExpression() {
if (getConstructor() == null && fArguments.length == 1) { ICPPFunction constructor = getConstructor();
if (constructor == null && fArguments.length == 1) {
// maybe EvalTypeID represents a conversion // maybe EvalTypeID represents a conversion
ICPPEvaluation conversionEval = maybeApplyConversion(fArguments[0], fInputType, false, false); ICPPEvaluation conversionEval = maybeApplyConversion(fArguments[0], fInputType, false, false);
if (isEquivalentTo(conversionEval)) { if (isEquivalentTo(conversionEval)) {
@ -244,9 +245,13 @@ public class EvalTypeId extends CPPDependentEvaluation {
if (!conversionEval.isConstantExpression()) if (!conversionEval.isConstantExpression())
return false; 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 @Override
@ -285,38 +290,35 @@ public class EvalTypeId extends CPPDependentEvaluation {
return null; return null;
IType simplifiedType = SemanticUtil.getNestedType(fInputType, TDEF | CVTYPE); IType simplifiedType = SemanticUtil.getNestedType(fInputType, TDEF | CVTYPE);
if (simplifiedType instanceof ICPPClassType) { if (simplifiedType instanceof ICPPClassType classType) {
ICPPClassType classType = (ICPPClassType) simplifiedType; if (fUsesBracedInitList) {
ICPPEvaluation[] arguments = fArguments; // (dcl.init.list)
ICPPConstructor[] constructors = classType.getConstructors(); EvalInitList evalInitList = new EvalInitList(fArguments, getTemplateDefinition());
if (fUsesBracedInitList && arguments.length > 0) {
// List-initialization of a class (dcl.init.list-3). try {
// e.g. A{1,2} // List-initialization of a class (dcl.init.list-3).
ICPPConstructor[] ctors = getInitializerListConstructors(constructors); // e.g. A{1,2}
if (ctors.length != 0) { IBinding binding = CPPSemantics.findConstructorForDirectListInitialization(classType, evalInitList,
constructors = ctors; null);
arguments = new EvalInitList[] { new EvalInitList(arguments, getTemplateDefinition()) }; if (binding instanceof ICPPConstructor constructor) {
} return constructor;
} else if (arguments.length == 1 && arguments[0] instanceof EvalInitList && !fUsesBracedInitList) { } else if (binding instanceof IProblemBinding) {
// List-initialization of a class (dcl.init.list-3). return new CPPFunction.CPPFunctionProblem(null, ISemanticProblem.BINDING_NOT_FOUND,
// e.g. A({1,2}) classType.getNameCharArray());
if (TypeTraits.isAggregateClass(classType)) { } else if (TypeTraits.isAggregateClass(classType)) {
// Pretend that aggregate initialization is calling the default constructor. // If Conversions.listInitializationSequence() did not returned problem binding,
return findDefaultConstructor(classType, constructors); // this is a list-initialization of aggregate class, and there is no constructor.
} return AGGREGATE_INITIALIZATION;
if (((EvalInitList) arguments[0]).getClauses().length == 0) { }
ICPPMethod ctor = findDefaultConstructor(classType, constructors); } catch (DOMException e) {
if (ctor != null) CCorePlugin.log(e);
return ctor;
}
ICPPConstructor[] ctors = getInitializerListConstructors(constructors);
if (ctors.length != 0) {
constructors = ctors;
} else {
arguments = ((EvalInitList) arguments[0]).getClauses();
} }
return null;
} }
ICPPEvaluation[] arguments = fArguments;
ICPPConstructor[] constructors = classType.getConstructors();
LookupData data = new LookupData(classType.getNameCharArray(), null, CPPSemantics.getCurrentLookupPoint()); LookupData data = new LookupData(classType.getNameCharArray(), null, CPPSemantics.getCurrentLookupPoint());
data.foundItems = constructors; data.foundItems = constructors;
data.setFunctionArguments(false, arguments); data.setFunctionArguments(false, arguments);

View file

@ -98,7 +98,7 @@ class FunctionCost {
return false; return false;
} }
public boolean performUDC() throws DOMException { public boolean performUDC(boolean noNarrowing) throws DOMException {
for (int i = 0; i < fCosts.length; i++) { for (int i = 0; i < fCosts.length; i++) {
Cost cost = fCosts[i]; Cost cost = fCosts[i];
Cost udcCost = null; Cost udcCost = null;
@ -107,12 +107,12 @@ class FunctionCost {
continue; continue;
case COPY_INIT_OF_CLASS: case COPY_INIT_OF_CLASS:
udcCost = Conversions.copyInitializationOfClass(fValueCategories[i], cost.source, udcCost = Conversions.copyInitializationOfClass(fValueCategories[i], cost.source,
(ICPPClassType) cost.target, false); (ICPPClassType) cost.target, false, noNarrowing);
break; break;
case INIT_BY_CONVERSION: case INIT_BY_CONVERSION:
IType uqSource = getNestedType(cost.source, TDEF | REF | CVTYPE); IType uqSource = getNestedType(cost.source, TDEF | REF | CVTYPE);
udcCost = Conversions.initializationByConversion(fValueCategories[i], cost.source, udcCost = Conversions.initializationByConversion(fValueCategories[i], cost.source,
(ICPPClassType) uqSource, cost.target, false, allowsContextualBooleanConversion()); (ICPPClassType) uqSource, cost.target, false, allowsContextualBooleanConversion(), noNarrowing);
break; break;
case LIST_INIT_OF_CLASS: case LIST_INIT_OF_CLASS:
udcCost = Conversions.listInitializationOfClass(((InitializerListType) cost.source).getEvaluation(), udcCost = Conversions.listInitializationOfClass(((InitializerListType) cost.source).getEvaluation(),
@ -126,6 +126,7 @@ class FunctionCost {
return false; return false;
} }
fCosts[i] = udcCost; fCosts[i] = udcCost;
if (!udcCost.converts()) { if (!udcCost.converts()) {
return false; return false;
} }

View file

@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2 Bundle-ManifestVersion: 2
Bundle-Name: %pluginName Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.cdt.ui; singleton:=true 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-Activator: org.eclipse.cdt.ui.CUIPlugin
Bundle-Vendor: %providerName Bundle-Vendor: %providerName
Bundle-Localization: plugin 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.ui.wizards.conversion,
org.eclipse.cdt.utils.ui.controls org.eclipse.cdt.utils.ui.controls
Import-Package: org.apache.commons.io;version="[2.8.0,3.0.0)" 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.compare;bundle-version="[3.8.500,4.0.0)",
org.eclipse.core.expressions;bundle-version="[3.8.200,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)", org.eclipse.core.filesystem;bundle-version="[1.9.500,2.0.0)",

View file

@ -180,7 +180,7 @@ public class ParameterGuesser {
private boolean isImplicitlyConvertible(IType orginType, IType candidateType) { private boolean isImplicitlyConvertible(IType orginType, IType candidateType) {
try { try {
Cost cost = Conversions.checkImplicitConversionSequence(orginType, candidateType, ValueCategory.LVALUE, Cost cost = Conversions.checkImplicitConversionSequence(orginType, candidateType, ValueCategory.LVALUE,
UDCMode.ALLOWED, Context.ORDINARY); UDCMode.ALLOWED, Context.ORDINARY, false);
if (cost.converts()) if (cost.converts())
return true; return true;
} catch (DOMException e) { } catch (DOMException e) {