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:
parent
57a47fe461
commit
36f16ba1b9
4 changed files with 55 additions and 21 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue