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

View file

@ -370,7 +370,7 @@ public class Value implements IValue {
* Tests whether the value depends on a template parameter.
*/
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.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.SemanticUtil;
/**
* For example in the constructor definition <br>

View file

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

View file

@ -43,6 +43,11 @@ public class CPPTemplateTypeArgument implements ICPPTemplateArgument {
return fType;
}
@Override
public ICPPEvaluation getNonTypeEvaluation() {
return null;
}
@Override
public IValue getNonTypeValue() {
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.ITypeMarshalBuffer;
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.ICPPUnknownBinding;
import org.eclipse.core.runtime.CoreException;
@ -112,9 +111,9 @@ public abstract class CPPEvaluation implements ICPPEvaluation {
@Override
public void marshalTemplateArgument(ICPPTemplateArgument arg) throws CoreException {
if (arg instanceof CPPTemplateNonTypeArgument) {
if (arg.isNonTypeValue()) {
putByte(VALUE);
((CPPTemplateNonTypeArgument) arg).getEvaluation().marshal(this, true);
arg.getNonTypeEvaluation().marshal(this, true);
} else {
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.IASTDeclarator;
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.IASTFunctionDeclarator;
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.IFunction;
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.IQualifierType;
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.ICPPASTElaboratedTypeSpecifier;
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.ICPPASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
@ -1074,13 +1075,11 @@ public class CPPTemplates {
if (arg == null)
return null;
if (arg.isNonTypeValue()) {
final IValue origValue= arg.getNonTypeValue();
final IType origType= arg.getTypeOfNonTypeValue();
final IValue instValue= instantiateValue(origValue, tpMap, packOffset, within, Value.MAX_RECURSION_DEPTH, point);
final IType instType= instantiateType(origType, tpMap, packOffset, within, point);
if (origType == instType && origValue == instValue)
final ICPPEvaluation eval = arg.getNonTypeEvaluation();
final ICPPEvaluation newEval= eval.instantiate(tpMap, packOffset, within, Value.MAX_RECURSION_DEPTH, point);
if (eval == newEval)
return arg;
return new CPPTemplateNonTypeArgument(instValue, instType);
return new CPPTemplateNonTypeArgument(newEval);
}
final IType orig= arg.getTypeValue();
@ -1676,11 +1675,9 @@ public class CPPTemplates {
IASTNode arg= args[i];
if (arg instanceof IASTTypeId) {
result[i]= new CPPTemplateTypeArgument(CPPVisitor.createType((IASTTypeId) arg));
} else if (arg instanceof IASTExpression) {
IASTExpression expr= (IASTExpression) arg;
IType type= expr.getExpressionType();
IValue value= Value.create((IASTExpression) arg, Value.MAX_RECURSION_DEPTH);
result[i]= new CPPTemplateNonTypeArgument(value, type);
} else if (arg instanceof ICPPASTExpression) {
ICPPASTExpression expr= (ICPPASTExpression) arg;
result[i]= new CPPTemplateNonTypeArgument(expr.getEvaluation());
} else {
throw new IllegalArgumentException("Unexpected type: " + arg.getClass().getName()); //$NON-NLS-1$
}
@ -2190,11 +2187,11 @@ public class CPPTemplates {
if (map != null && pType != null) {
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 null;
return convertNonTypeTemplateArgument(pType, arg, point);
} catch (DOMException e) {
return null;
}
@ -2257,22 +2254,45 @@ public class CPPTemplates {
}
/**
* Returns whether the template argument <code>arg</code> can be converted to
* the same type as <code>paramType</code> using the rules specified in 14.3.2.5.
* @param paramType
* @param arg
* @return
* Converts the template argument <code>arg</code> to match the parameter type
* <code>paramType</code> or returns <code>null</code>, if this violates the rules
* specified in 14.3.2 - 5.
* @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
IType a= arg.getTypeOfNonTypeValue();
IType p;
if (paramType instanceof IFunctionType) {
paramType = new CPPPointerType(paramType);
p = new CPPPointerType(paramType);
} 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) {
@ -2320,7 +2340,7 @@ public class CPPTemplates {
if (arg.isTypeValue())
return isDependentType(arg.getTypeValue());
return Value.isDependentValue(arg.getNonTypeValue());
return arg.getNonTypeEvaluation().isValueDependent();
}
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);
} else if (fBinding instanceof ICPPTemplateNonTypeParameter) {
ICPPTemplateArgument argument = tpMap.getArgument((ICPPTemplateNonTypeParameter) fBinding);
if (argument != null) {
IValue value = argument.getNonTypeValue();
return new EvalFixed(null, ValueCategory.PRVALUE, value);
if (argument != null && argument.isNonTypeValue()) {
return argument.getNonTypeEvaluation();
}
// TODO(sprigogin): Do we need something similar for pack expansion?
} else if (fBinding instanceof ICPPUnknownBinding) {

View file

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

View file

@ -437,6 +437,9 @@ public class SemanticUtil {
}
public static IType mapToAST(IType type, IASTNode node) {
if (node == null)
return type;
if (type instanceof IFunctionType) {
final ICPPFunctionType ft = (ICPPFunctionType) type;
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.ICPPTemplateDefinition;
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.ICPPTemplateTemplateParameter;
import org.eclipse.cdt.internal.core.dom.parser.Value;
@ -185,6 +186,20 @@ public class TemplateArgumentDeduction {
if (!map.addDeducedArgs(deduct.fDeducedArgs))
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);
} catch (DOMException e) {
}
@ -649,8 +664,6 @@ public class TemplateArgumentDeduction {
if (Value.referencesTemplateParameter(tval)) {
int parId= Value.isTemplateParameter(tval);
if (parId >= 0) {
if (!p.getTypeOfNonTypeValue().isSameType(a.getTypeOfNonTypeValue()))
return false;
ICPPTemplateArgument old= fDeducedArgs.getArgument(parId, fPackOffset);
if (old == null) {
return deduce(parId, a);

View file

@ -93,14 +93,16 @@ public class TemplateInstanceUtil {
}
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();
IType t= cf.getCompositeType(typeValue);
if (t != typeValue) {
return new CPPTemplateTypeArgument(t);
}
} else if (arg instanceof CPPTemplateNonTypeArgument) {
ICPPEvaluation eval = ((CPPTemplateNonTypeArgument) arg).getEvaluation();
} else {
ICPPEvaluation eval = arg.getNonTypeEvaluation();
ICPPEvaluation eval2 = ((CPPCompositesFactory) cf).getCompositeEvaluation(eval);
if (eval2 != eval) {
return new CPPTemplateNonTypeArgument(eval2);

View file

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