1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 22:52:11 +02:00

Bug 486426 - Constexpr evaluation of function call with an argument requiring user-defined conversion

Change-Id: I1110b76d3520666a980100f6cd17689911a16759
This commit is contained in:
Nathan Ridge 2016-01-27 02:03:34 -05:00 committed by Gerrit Code Review @ Eclipse.org
parent 57a47fe461
commit 36f16ba1b9
4 changed files with 55 additions and 21 deletions

View file

@ -8803,6 +8803,22 @@ public class AST2TemplateTests extends AST2TestBase {
parseAndCheckBindings();
}
// constexpr bool negate(bool arg) {
// return !arg;
// }
//
// template <bool B>
// struct boolean {
// constexpr operator bool() { return B; }
// };
//
// constexpr bool waldo = negate(boolean<true>());
public void testDependentConversionOperator_486426() throws Exception {
BindingAssertionHelper helper = getAssertionHelper();
ICPPVariable waldo = helper.assertNonProblem("waldo");
assertConstantValue(0, waldo);
}
// template <typename>
// struct C {
// friend bool operator==(C, C);

View file

@ -13,9 +13,12 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.DOMException;
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.IType;
import org.eclipse.cdt.core.dom.ast.IValue;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
@ -115,4 +118,34 @@ public abstract class CPPEvaluation implements ICPPEvaluation {
protected static boolean isNullOrConstexprFunc(ICPPFunction function) {
return function == null || function.isConstexpr();
}
/**
* If a user-defined conversion is required to convert 'argument' to type 'targetType',
* return 'argument' wrapped in an evaluation representing the conversion.
* Otherwise, return 'argument' unmodified.
* @param point point of instantiation for name lookups
*/
protected static ICPPEvaluation maybeApplyConversion(ICPPEvaluation argument, IType targetType,
IASTNode point) {
IType type = argument.getType(point);
ValueCategory valueCategory = argument.getValueCategory(point);
ICPPFunction conversion = null;
if (type instanceof ICPPClassType) {
try {
Cost cost = Conversions.initializationByConversion(valueCategory, type, (ICPPClassType) type,
targetType, false, point);
conversion = cost.getUserDefinedConversion();
} catch (DOMException e) {
CCorePlugin.log(e);
}
}
if (conversion != null) {
if (!conversion.isConstexpr()) {
return EvalFixed.INCOMPLETE;
}
ICPPEvaluation eval = new EvalBinding(conversion, null, (IBinding) null);
argument = new EvalFunctionCall(new ICPPEvaluation[] {eval, argument}, (IBinding) null);
}
return argument;
}
}

View file

@ -247,11 +247,11 @@ public class EvalFunctionCall extends CPPDependentEvaluation {
ICPPEvaluation eval = CPPFunction.getReturnExpression(function, context.getPoint());
if (eval == null)
return EvalFixed.INCOMPLETE;
CPPFunctionParameterMap parameterMap = buildParameterMap(function);
CPPFunctionParameterMap parameterMap = buildParameterMap(function, context.getPoint());
return eval.computeForFunctionCall(parameterMap, context.recordStep());
}
private CPPFunctionParameterMap buildParameterMap(ICPPFunction function) {
private CPPFunctionParameterMap buildParameterMap(ICPPFunction function, IASTNode point) {
ICPPParameter[] parameters = function.getParameters();
CPPFunctionParameterMap map = new CPPFunctionParameterMap(parameters.length);
int j = 1;
@ -262,7 +262,8 @@ public class EvalFunctionCall extends CPPDependentEvaluation {
j = fArguments.length;
} else {
if (j < fArguments.length) {
map.put(i, fArguments[j++]);
ICPPEvaluation argument = maybeApplyConversion(fArguments[j++], param.getType(), point);
map.put(i, argument);
} else if (param.hasDefaultValue()) {
IValue value = param.getDefaultValue();
ICPPEvaluation eval = value.getEvaluation();

View file

@ -37,7 +37,6 @@ import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUti
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.REF;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.TDEF;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
import org.eclipse.cdt.core.dom.ast.IASTNode;
@ -47,7 +46,6 @@ import org.eclipse.cdt.core.dom.ast.IPointerType;
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.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMember;
@ -285,22 +283,8 @@ public class EvalUnary extends CPPDependentEvaluation {
if (overload != null) {
ICPPFunctionType functionType = overload.getType();
IType targetType = functionType.getParameterTypes()[0];
ValueCategory valueCategory = fArgument.getValueCategory(point);
IType type = fArgument.getType(point);
ICPPFunction conversion = null;
try {
Cost cost = Conversions.initializationByConversion(valueCategory, type, (ICPPClassType) type, targetType, false, point);
conversion = cost.getUserDefinedConversion();
} catch (DOMException e) {
CCorePlugin.log(e);
}
arg = maybeApplyConversion(arg, targetType, point);
if (conversion != null) {
if (!conversion.isConstexpr())
return Value.ERROR;
ICPPEvaluation eval = new EvalBinding(conversion, null, (IBinding) null);
arg = new EvalFunctionCall(new ICPPEvaluation[] {eval, arg}, (IBinding) null);
}
if (!(overload instanceof CPPImplicitFunction)) {
if (!overload.isConstexpr())
return Value.ERROR;