1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Bug 372587: Argument deduction for function call.

This commit is contained in:
Markus Schorn 2012-11-08 14:16:35 -08:00 committed by Sergey Prigogin
parent 1e9babd7b5
commit 33e98cd876
14 changed files with 105 additions and 53 deletions

View file

@ -65,11 +65,10 @@ public class BinaryRunner {
ICElement root = factory.getCModel(); ICElement root = factory.getCModel();
CElementDelta cdelta = new CElementDelta(root); CElementDelta cdelta = new CElementDelta(root);
cdelta.changed(cproj, ICElementDelta.F_CONTENT); cdelta.changed(cproj, ICElementDelta.F_CONTENT);
for (int j = 0; j < containers.length; ++j) { for (IParent container : containers) {
if (fMonitor.isCanceled()) { if (fMonitor.isCanceled()) {
return; return;
} }
IParent container = containers[j];
ICElement[] children = container.getChildren(); ICElement[] children = container.getChildren();
if (children.length > 0) { if (children.length > 0) {
cdelta.added((ICElement)container); cdelta.added((ICElement)container);
@ -171,9 +170,9 @@ public class BinaryRunner {
} }
private class Visitor implements IResourceProxyVisitor { private class Visitor implements IResourceProxyVisitor {
private IProgressMonitor vMonitor; private final IProgressMonitor vMonitor;
private IProject project; private final IProject project;
private IContentType textContentType; private final IContentType textContentType;
public Visitor(IProgressMonitor monitor) { public Visitor(IProgressMonitor monitor) {
vMonitor = monitor; vMonitor = monitor;
@ -200,7 +199,7 @@ public class BinaryRunner {
// check against known content types // check against known content types
// if the file has an extension // if the file has an extension
String name = proxy.getName(); String name = proxy.getName();
if (name.contains(".")) { if (name.contains(".")) { //$NON-NLS-1$
IContentType contentType = CCorePlugin.getContentType(project, name); IContentType contentType = CCorePlugin.getContentType(project, name);
if (contentType != null && textContentType != null) { if (contentType != null && textContentType != null) {
if (contentType.isKindOf(textContentType)) { if (contentType.isKindOf(textContentType)) {
@ -217,8 +216,8 @@ public class BinaryRunner {
// we have a candidate // we have a candidate
IPath path = proxy.requestFullPath(); IPath path = proxy.requestFullPath();
if (path != null) { if (path != null) {
for (int i = 0; i < entries.length; ++i) { for (IOutputEntry entrie : entries) {
if (isOnOutputEntry(entries[i], path)) { if (isOnOutputEntry(entrie, path)) {
IFile file = (IFile) proxy.requestResource(); IFile file = (IFile) proxy.requestResource();
CModelManager factory = CModelManager.getDefault(); CModelManager factory = CModelManager.getDefault();
IBinaryFile bin = factory.createBinaryFile(file); IBinaryFile bin = factory.createBinaryFile(file);

View file

@ -12,6 +12,7 @@ package org.eclipse.cdt.core.dom.ast.cpp;
import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.IValue; import org.eclipse.cdt.core.dom.ast.IValue;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation;
/** /**
* Models the value of a template parameter or for the argument of a template-id. * Models the value of a template parameter or for the argument of a template-id.
@ -42,6 +43,14 @@ public interface ICPPTemplateArgument {
*/ */
IType getTypeValue(); IType getTypeValue();
/**
* If this is a non-type value (suitable for a template non-type parameters),
* the evaluation object is returned.
* For type values, <code>null</code> is returned.
* @noreference This method is not intended to be referenced by clients.
*/
ICPPEvaluation getNonTypeEvaluation();
/** /**
* If this is a non-type value (suitable for a template non-type parameters), * If this is a non-type value (suitable for a template non-type parameters),
* the value is returned. * the value is returned.

View file

@ -370,7 +370,7 @@ public class Value implements IValue {
* Tests whether the value depends on a template parameter. * Tests whether the value depends on a template parameter.
*/ */
public static boolean isDependentValue(IValue nonTypeValue) { public static boolean isDependentValue(IValue nonTypeValue) {
return nonTypeValue.getEvaluation() != null; return nonTypeValue != null && nonTypeValue.getEvaluation() != null;
} }
/** /**

View file

@ -35,7 +35,6 @@ import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.core.parser.util.CharArraySet; import org.eclipse.cdt.core.parser.util.CharArraySet;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode; import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil;
/** /**
* For example in the constructor definition <br> * For example in the constructor definition <br>

View file

@ -51,6 +51,11 @@ public class CPPTemplateNonTypeArgument implements ICPPTemplateArgument {
return null; return null;
} }
@Override
public ICPPEvaluation getNonTypeEvaluation() {
return fEvaluation;
}
@Override @Override
public IValue getNonTypeValue() { public IValue getNonTypeValue() {
return fEvaluation.getValue(null); return fEvaluation.getValue(null);
@ -94,8 +99,4 @@ public class CPPTemplateNonTypeArgument implements ICPPTemplateArgument {
public String toString() { public String toString() {
return getNonTypeValue().toString(); return getNonTypeValue().toString();
} }
public ICPPEvaluation getEvaluation() {
return fEvaluation;
}
} }

View file

@ -43,6 +43,11 @@ public class CPPTemplateTypeArgument implements ICPPTemplateArgument {
return fType; return fType;
} }
@Override
public ICPPEvaluation getNonTypeEvaluation() {
return null;
}
@Override @Override
public IValue getNonTypeValue() { public IValue getNonTypeValue() {
return null; return null;

View file

@ -27,7 +27,6 @@ import org.eclipse.cdt.internal.core.dom.parser.ISerializableEvaluation;
import org.eclipse.cdt.internal.core.dom.parser.ISerializableType; import org.eclipse.cdt.internal.core.dom.parser.ISerializableType;
import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer; import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer;
import org.eclipse.cdt.internal.core.dom.parser.Value; import org.eclipse.cdt.internal.core.dom.parser.Value;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateNonTypeArgument;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
@ -112,9 +111,9 @@ public abstract class CPPEvaluation implements ICPPEvaluation {
@Override @Override
public void marshalTemplateArgument(ICPPTemplateArgument arg) throws CoreException { public void marshalTemplateArgument(ICPPTemplateArgument arg) throws CoreException {
if (arg instanceof CPPTemplateNonTypeArgument) { if (arg.isNonTypeValue()) {
putByte(VALUE); putByte(VALUE);
((CPPTemplateNonTypeArgument) arg).getEvaluation().marshal(this, true); arg.getNonTypeEvaluation().marshal(this, true);
} else { } else {
marshalType(arg.getTypeValue()); marshalType(arg.getTypeValue());
} }

View file

@ -29,7 +29,6 @@ import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTExpression;
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory; import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
@ -44,6 +43,7 @@ import org.eclipse.cdt.core.dom.ast.IEnumeration;
import org.eclipse.cdt.core.dom.ast.IEnumerator; import org.eclipse.cdt.core.dom.ast.IEnumerator;
import org.eclipse.cdt.core.dom.ast.IFunction; import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.dom.ast.IFunctionType; import org.eclipse.cdt.core.dom.ast.IFunctionType;
import org.eclipse.cdt.core.dom.ast.IPointerType;
import org.eclipse.cdt.core.dom.ast.IProblemBinding; import org.eclipse.cdt.core.dom.ast.IProblemBinding;
import org.eclipse.cdt.core.dom.ast.IQualifierType; import org.eclipse.cdt.core.dom.ast.IQualifierType;
import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IScope;
@ -56,6 +56,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBas
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNamedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
@ -1074,13 +1075,11 @@ public class CPPTemplates {
if (arg == null) if (arg == null)
return null; return null;
if (arg.isNonTypeValue()) { if (arg.isNonTypeValue()) {
final IValue origValue= arg.getNonTypeValue(); final ICPPEvaluation eval = arg.getNonTypeEvaluation();
final IType origType= arg.getTypeOfNonTypeValue(); final ICPPEvaluation newEval= eval.instantiate(tpMap, packOffset, within, Value.MAX_RECURSION_DEPTH, point);
final IValue instValue= instantiateValue(origValue, tpMap, packOffset, within, Value.MAX_RECURSION_DEPTH, point); if (eval == newEval)
final IType instType= instantiateType(origType, tpMap, packOffset, within, point);
if (origType == instType && origValue == instValue)
return arg; return arg;
return new CPPTemplateNonTypeArgument(instValue, instType); return new CPPTemplateNonTypeArgument(newEval);
} }
final IType orig= arg.getTypeValue(); final IType orig= arg.getTypeValue();
@ -1676,11 +1675,9 @@ public class CPPTemplates {
IASTNode arg= args[i]; IASTNode arg= args[i];
if (arg instanceof IASTTypeId) { if (arg instanceof IASTTypeId) {
result[i]= new CPPTemplateTypeArgument(CPPVisitor.createType((IASTTypeId) arg)); result[i]= new CPPTemplateTypeArgument(CPPVisitor.createType((IASTTypeId) arg));
} else if (arg instanceof IASTExpression) { } else if (arg instanceof ICPPASTExpression) {
IASTExpression expr= (IASTExpression) arg; ICPPASTExpression expr= (ICPPASTExpression) arg;
IType type= expr.getExpressionType(); result[i]= new CPPTemplateNonTypeArgument(expr.getEvaluation());
IValue value= Value.create((IASTExpression) arg, Value.MAX_RECURSION_DEPTH);
result[i]= new CPPTemplateNonTypeArgument(value, type);
} else { } else {
throw new IllegalArgumentException("Unexpected type: " + arg.getClass().getName()); //$NON-NLS-1$ throw new IllegalArgumentException("Unexpected type: " + arg.getClass().getName()); //$NON-NLS-1$
} }
@ -2190,11 +2187,11 @@ public class CPPTemplates {
if (map != null && pType != null) { if (map != null && pType != null) {
pType= instantiateType(pType, map, -1, null, point); pType= instantiateType(pType, map, -1, null, point);
} }
if (argType instanceof ICPPUnknownType || argType instanceof ISemanticProblem || isNonTypeArgumentConvertible(pType, argType, point)) {
if (argType instanceof ICPPUnknownType) {
return new CPPTemplateNonTypeArgument(arg.getNonTypeValue(), pType); return new CPPTemplateNonTypeArgument(arg.getNonTypeValue(), pType);
} }
return null; return convertNonTypeTemplateArgument(pType, arg, point);
} catch (DOMException e) { } catch (DOMException e) {
return null; return null;
} }
@ -2257,22 +2254,45 @@ public class CPPTemplates {
} }
/** /**
* Returns whether the template argument <code>arg</code> can be converted to * Converts the template argument <code>arg</code> to match the parameter type
* the same type as <code>paramType</code> using the rules specified in 14.3.2.5. * <code>paramType</code> or returns <code>null</code>, if this violates the rules
* @param paramType * specified in 14.3.2 - 5.
* @param arg
* @return
* @throws DOMException * @throws DOMException
*/ */
private static boolean isNonTypeArgumentConvertible(IType paramType, IType arg, IASTNode point) throws DOMException { private static ICPPTemplateArgument convertNonTypeTemplateArgument(final IType paramType, ICPPTemplateArgument arg, IASTNode point) throws DOMException {
//14.1s8 function to pointer and array to pointer conversions //14.1s8 function to pointer and array to pointer conversions
IType a= arg.getTypeOfNonTypeValue();
IType p;
if (paramType instanceof IFunctionType) { if (paramType instanceof IFunctionType) {
paramType = new CPPPointerType(paramType); p = new CPPPointerType(paramType);
} else if (paramType instanceof IArrayType) { } else if (paramType instanceof IArrayType) {
paramType = new CPPPointerType(((IArrayType) paramType).getType()); p = new CPPPointerType(((IArrayType) paramType).getType());
} else {
p= paramType;
if (p.isSameType(a))
return arg;
} }
Cost cost = Conversions.checkImplicitConversionSequence(paramType, arg, LVALUE, UDCMode.FORBIDDEN, Context.ORDINARY, point);
return cost != null && cost.converts(); if (a instanceof FunctionSetType) {
if (p instanceof IPointerType) {
p= ((IPointerType) p).getType();
}
if (p instanceof IFunctionType) {
final CPPFunctionSet functionSet = ((FunctionSetType) a).getFunctionSet();
for (ICPPFunction f : functionSet.getBindings()) {
if (p.isSameType(f.getType())) {
functionSet.applySelectedFunction(f);
return new CPPTemplateNonTypeArgument(new EvalBinding(f, null));
}
}
}
return null;
}
Cost cost = Conversions.checkImplicitConversionSequence(p, a, LVALUE, UDCMode.FORBIDDEN, Context.ORDINARY, point);
if (cost == null || !cost.converts())
return null;
return new CPPTemplateNonTypeArgument(arg.getNonTypeValue(), paramType);
} }
static boolean argsAreTrivial(ICPPTemplateParameter[] pars, ICPPTemplateArgument[] args) { static boolean argsAreTrivial(ICPPTemplateParameter[] pars, ICPPTemplateArgument[] args) {
@ -2320,7 +2340,7 @@ public class CPPTemplates {
if (arg.isTypeValue()) if (arg.isTypeValue())
return isDependentType(arg.getTypeValue()); return isDependentType(arg.getTypeValue());
return Value.isDependentValue(arg.getNonTypeValue()); return arg.getNonTypeEvaluation().isValueDependent();
} }
public static boolean containsDependentType(List<IType> ts) { public static boolean containsDependentType(List<IType> ts) {

View file

@ -223,9 +223,8 @@ public class EvalBinding extends CPPEvaluation {
return new EvalFixed(type, ValueCategory.PRVALUE, value); return new EvalFixed(type, ValueCategory.PRVALUE, value);
} else if (fBinding instanceof ICPPTemplateNonTypeParameter) { } else if (fBinding instanceof ICPPTemplateNonTypeParameter) {
ICPPTemplateArgument argument = tpMap.getArgument((ICPPTemplateNonTypeParameter) fBinding); ICPPTemplateArgument argument = tpMap.getArgument((ICPPTemplateNonTypeParameter) fBinding);
if (argument != null) { if (argument != null && argument.isNonTypeValue()) {
IValue value = argument.getNonTypeValue(); return argument.getNonTypeEvaluation();
return new EvalFixed(null, ValueCategory.PRVALUE, value);
} }
// TODO(sprigogin): Do we need something similar for pack expansion? // TODO(sprigogin): Do we need something similar for pack expansion?
} else if (fBinding instanceof ICPPUnknownBinding) { } else if (fBinding instanceof ICPPUnknownBinding) {

View file

@ -238,6 +238,9 @@ public class EvalUnary extends CPPEvaluation {
} }
IValue val = fArgument.getValue(point); IValue val = fArgument.getValue(point);
if (val == null)
return Value.UNKNOWN;
Long num = val.numericalValue(); Long num = val.numericalValue();
if (num != null) { if (num != null) {
return Value.evaluateUnaryExpression(fOperator, num); return Value.evaluateUnaryExpression(fOperator, num);

View file

@ -437,6 +437,9 @@ public class SemanticUtil {
} }
public static IType mapToAST(IType type, IASTNode node) { public static IType mapToAST(IType type, IASTNode node) {
if (node == null)
return type;
if (type instanceof IFunctionType) { if (type instanceof IFunctionType) {
final ICPPFunctionType ft = (ICPPFunctionType) type; final ICPPFunctionType ft = (ICPPFunctionType) type;
final IType r = ft.getReturnType(); final IType r = ft.getReturnType();

View file

@ -54,6 +54,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTemplateParameter;
import org.eclipse.cdt.internal.core.dom.parser.Value; import org.eclipse.cdt.internal.core.dom.parser.Value;
@ -185,6 +186,20 @@ public class TemplateArgumentDeduction {
if (!map.addDeducedArgs(deduct.fDeducedArgs)) if (!map.addDeducedArgs(deduct.fDeducedArgs))
return false; return false;
// 14.8.2.5 - 17
for (ICPPTemplateParameter tpar : tmplPars) {
if (tpar instanceof ICPPTemplateNonTypeParameter) {
ICPPTemplateArgument arg = deduct.fDeducedArgs.getArgument(tpar);
if (arg != null) {
IType type1 = ((ICPPTemplateNonTypeParameter) tpar).getType();
type1= CPPTemplates.instantiateType(type1, map, -1, null, point);
IType type2= arg.getTypeOfNonTypeValue();
if (!type1.isSameType(type2))
return false;
}
}
}
return verifyDeduction(tmplPars, map, true, point); return verifyDeduction(tmplPars, map, true, point);
} catch (DOMException e) { } catch (DOMException e) {
} }
@ -649,8 +664,6 @@ public class TemplateArgumentDeduction {
if (Value.referencesTemplateParameter(tval)) { if (Value.referencesTemplateParameter(tval)) {
int parId= Value.isTemplateParameter(tval); int parId= Value.isTemplateParameter(tval);
if (parId >= 0) { if (parId >= 0) {
if (!p.getTypeOfNonTypeValue().isSameType(a.getTypeOfNonTypeValue()))
return false;
ICPPTemplateArgument old= fDeducedArgs.getArgument(parId, fPackOffset); ICPPTemplateArgument old= fDeducedArgs.getArgument(parId, fPackOffset);
if (old == null) { if (old == null) {
return deduce(parId, a); return deduce(parId, a);

View file

@ -93,14 +93,16 @@ public class TemplateInstanceUtil {
} }
static ICPPTemplateArgument convert(ICompositesFactory cf, ICPPTemplateArgument arg) throws DOMException { static ICPPTemplateArgument convert(ICompositesFactory cf, ICPPTemplateArgument arg) throws DOMException {
if (arg instanceof CPPTemplateTypeArgument) { if (arg == null)
return null;
if (arg.isTypeValue()) {
final IType typeValue = arg.getTypeValue(); final IType typeValue = arg.getTypeValue();
IType t= cf.getCompositeType(typeValue); IType t= cf.getCompositeType(typeValue);
if (t != typeValue) { if (t != typeValue) {
return new CPPTemplateTypeArgument(t); return new CPPTemplateTypeArgument(t);
} }
} else if (arg instanceof CPPTemplateNonTypeArgument) { } else {
ICPPEvaluation eval = ((CPPTemplateNonTypeArgument) arg).getEvaluation(); ICPPEvaluation eval = arg.getNonTypeEvaluation();
ICPPEvaluation eval2 = ((CPPCompositesFactory) cf).getCompositeEvaluation(eval); ICPPEvaluation eval2 = ((CPPCompositesFactory) cf).getCompositeEvaluation(eval);
if (eval2 != eval) { if (eval2 != eval) {
return new CPPTemplateNonTypeArgument(eval2); return new CPPTemplateNonTypeArgument(eval2);

View file

@ -189,9 +189,9 @@ public class TypeMarshalBuffer implements ITypeMarshalBuffer {
@Override @Override
public void marshalTemplateArgument(ICPPTemplateArgument arg) throws CoreException { public void marshalTemplateArgument(ICPPTemplateArgument arg) throws CoreException {
if (arg instanceof CPPTemplateNonTypeArgument) { if (arg.isNonTypeValue()) {
putByte(VALUE); putByte(VALUE);
((CPPTemplateNonTypeArgument) arg).getEvaluation().marshal(this, true); arg.getNonTypeEvaluation().marshal(this, true);
} else { } else {
marshalType(arg.getTypeValue()); marshalType(arg.getTypeValue());
} }