1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-03 06:15:37 +02:00

Bug 326900: Partial ordering of conversion-operators.

This commit is contained in:
Markus Schorn 2010-10-08 08:16:15 +00:00
parent 08367b0204
commit 7f63bc2647
5 changed files with 87 additions and 33 deletions

View file

@ -5113,4 +5113,27 @@ public class AST2TemplateTests extends AST2BaseTest {
public void testADLForTemplateSpecializations_Bug327069() throws Exception {
parseAndCheckBindings();
}
// template<typename T, typename V> T* f(V*);
// template<typename T, typename V> T f(V*);
// template<typename T, typename V> T* f(V);
// void x(int* (*) (int*)) {
// x(f);
// }
public void testPartialOrderingInNonCallContext_Bug326900() throws Exception {
parseAndCheckBindings();
}
// struct X {
// template<typename T> operator T();
// template<typename T> operator T*();
// };
// void y(int *) {
// X x;
// y(x);
// }
public void testPartialOrderingForConversions_Bug326900() throws Exception {
parseAndCheckBindings();
}
}

View file

@ -200,6 +200,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownClassType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates.TypeSelection;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions.Context;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions.UDCMode;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.Rank;
@ -2346,7 +2347,7 @@ public class CPPSemantics {
// Loop over all functions
List<FunctionCost> potentialCosts= null;
for (IFunction fn : fns) {
for (ICPPFunction fn : fns) {
if (fn == null)
continue;
@ -2516,12 +2517,12 @@ public class CPPSemantics {
}
}
private static FunctionCost costForFunctionCall(IFunction fn, boolean allowUDC, LookupData data)
private static FunctionCost costForFunctionCall(ICPPFunction fn, boolean allowUDC, LookupData data)
throws DOMException {
IType[] argTypes = data.getFunctionArgumentTypes();
ValueCategory[] isLValue= data.getFunctionArgumentValueCategories();
int skipArg= 0;
final ICPPFunctionType ftype= (ICPPFunctionType) fn.getType();
final ICPPFunctionType ftype= fn.getType();
if (ftype == null)
return null;
@ -2836,7 +2837,7 @@ public class CPPSemantics {
if (inst != null) {
int cmp= -1;
if (result != null) {
cmp= CPPTemplates.orderFunctionTemplates(resultTemplate, template);
cmp= CPPTemplates.orderFunctionTemplates(resultTemplate, template, TypeSelection.PARAMETERS_AND_RETURN_TYPE);
if (cmp == 0)
cmp= compareByRelevance(tu, resultTemplate, template);
}

View file

@ -152,6 +152,7 @@ public class CPPTemplates {
private static final int PACK_SIZE_FAIL = -2;
private static final int PACK_SIZE_NOT_FOUND = Integer.MAX_VALUE;
private static final ICPPFunction[] NO_FUNCTIONS = {};
static enum TypeSelection {PARAMETERS, RETURN_TYPE, PARAMETERS_AND_RETURN_TYPE}
/**
* Instantiates a class template with the given arguments. May return <code>null</code>.
@ -1683,10 +1684,10 @@ public class CPPTemplates {
}
// 14.5.6.2 Partial ordering of function templates
static int orderFunctionTemplates(ICPPFunctionTemplate f1, ICPPFunctionTemplate f2)
static int orderFunctionTemplates(ICPPFunctionTemplate f1, ICPPFunctionTemplate f2, TypeSelection mode)
throws DOMException {
int s1 = compareSpecialization(f1, f2);
int s2 = compareSpecialization(f2, f1);
int s1 = compareSpecialization(f1, f2, mode);
int s2 = compareSpecialization(f2, f1, mode);
if (s1 == s2)
return 0;
@ -1731,22 +1732,38 @@ public class CPPTemplates {
return arg;
}
private static int compareSpecialization(ICPPFunctionTemplate f1, ICPPFunctionTemplate f2) throws DOMException {
private static int compareSpecialization(ICPPFunctionTemplate f1, ICPPFunctionTemplate f2, TypeSelection mode) throws DOMException {
ICPPFunction transF1 = transferFunctionTemplate(f1);
if (transF1 == null)
return -1;
// mstodo use function-type, parameter-types or return type.
IType[] pars= f2.getType().getParameterTypes();
IType[] args = transF1.getType().getParameterTypes();
boolean nonStaticMember1= isNonStaticMember(f1);
boolean nonStaticMember2= isNonStaticMember(f2);
if (nonStaticMember1 != nonStaticMember2) {
if (nonStaticMember1) {
args= addImplicitObjectType(args, (ICPPMethod) f1);
} else {
pars= addImplicitObjectType(pars, (ICPPMethod) f2);
final ICPPFunctionType ft2 = f2.getType();
final ICPPFunctionType transFt1 = transF1.getType();
IType[] pars;
IType[] args;
switch(mode) {
case RETURN_TYPE:
pars= new IType[] {ft2.getReturnType()};
args= new IType[] {transFt1.getReturnType()};
break;
case PARAMETERS_AND_RETURN_TYPE:
pars= concat(ft2.getReturnType(), ft2.getParameterTypes());
args= concat(transFt1.getReturnType(), transFt1.getParameterTypes());
break;
case PARAMETERS:
default:
pars= ft2.getParameterTypes();
args = transFt1.getParameterTypes();
boolean nonStaticMember1= isNonStaticMember(f1);
boolean nonStaticMember2= isNonStaticMember(f2);
if (nonStaticMember1 != nonStaticMember2) {
if (nonStaticMember1) {
args= addImplicitObjectType(args, (ICPPMethod) f1);
} else {
pars= addImplicitObjectType(pars, (ICPPMethod) f2);
}
}
break;
}
return TemplateArgumentDeduction.deduceForPartialOrdering(f2.getTemplateParameters(), pars, args);
}
@ -1760,16 +1777,21 @@ public class CPPTemplates {
if (ct != null) {
try {
ICPPFunctionType ft = f1.getType();
IType[] result= new IType[types.length+1];
result[0]= new CPPReferenceType(addQualifiers(ct, ft.isConst(), ft.isVolatile()), false);
System.arraycopy(types, 0, result, 1, types.length);
return result;
final CPPReferenceType t = new CPPReferenceType(addQualifiers(ct, ft.isConst(), ft.isVolatile()), false);
return concat(t, types);
} catch (DOMException e) {
}
}
return types;
}
private static IType[] concat(final IType t, IType[] types) {
IType[] result= new IType[types.length+1];
result[0]= t;
System.arraycopy(types, 0, result, 1, types.length);
return result;
}
private static ICPPClassTemplatePartialSpecialization findPartialSpecialization(ICPPClassTemplate ct,
ICPPTemplateArgument[] args) throws DOMException {
ICPPClassTemplatePartialSpecialization[] pspecs = ct.getPartialSpecializations();

View file

@ -10,6 +10,8 @@
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates.TypeSelection.PARAMETERS;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates.TypeSelection.RETURN_TYPE;
import static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
import org.eclipse.cdt.core.dom.ast.DOMException;
@ -19,26 +21,28 @@ import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.dom.ast.IType;
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.ICPPFunctionTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates.TypeSelection;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.DeferredUDC;
/**
* Cost for the entire function call
*/
class FunctionCost {
private final IFunction fFunction;
private final ICPPFunction fFunction;
private final Cost[] fCosts;
private final ValueCategory[] fValueCategories;
private boolean fIsDirectCopyCtor;
public FunctionCost(IFunction fn, int paramCount) {
public FunctionCost(ICPPFunction fn, int paramCount) {
fFunction= fn;
fCosts= new Cost[paramCount];
fValueCategories= new ValueCategory[paramCount];
}
public FunctionCost(IFunction fn, Cost cost) {
public FunctionCost(ICPPFunction fn, Cost cost) {
fFunction= fn;
fCosts= new Cost[] {cost};
fValueCategories= null; // no udc will be performed
@ -57,7 +61,7 @@ class FunctionCost {
fValueCategories[idx]= valueCat;
}
public IFunction getFunction() {
public ICPPFunction getFunction() {
return fFunction;
}
@ -155,7 +159,8 @@ class FunctionCost {
} else if (!isTemplate && otherIsTemplate) {
haveBetter = true;
} else if (isTemplate && otherIsTemplate) {
int order = CPPTemplates.orderFunctionTemplates(otherAsTemplate, asTemplate);
TypeSelection ts= SemanticUtil.isConversionOperator(getFunction()) ? RETURN_TYPE : PARAMETERS;
int order = CPPTemplates.orderFunctionTemplates(otherAsTemplate, asTemplate, ts);
if (order < 0) {
haveBetter= true;
} else if (order > 0) {

View file

@ -31,6 +31,7 @@ import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
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.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
@ -156,11 +157,13 @@ public class SemanticUtil {
* @param method
* @return true if the specified method is a conversion operator
*/
public static final boolean isConversionOperator(ICPPMethod method) {
final char[] name= method.getNameCharArray();
if (name.length > OPERATOR_CHARS.length + 1 && name[OPERATOR_CHARS.length] == ' ' &&
CharArrayUtils.equals(name, 0, OPERATOR_CHARS.length, OPERATOR_CHARS)) {
return !cas.containsKey(name, OPERATOR_CHARS.length + 1, name.length - (OPERATOR_CHARS.length+1));
public static final boolean isConversionOperator(ICPPFunction method) {
if (method instanceof ICPPMethod) {
final char[] name= method.getNameCharArray();
if (name.length > OPERATOR_CHARS.length + 1 && name[OPERATOR_CHARS.length] == ' ' &&
CharArrayUtils.equals(name, 0, OPERATOR_CHARS.length, OPERATOR_CHARS)) {
return !cas.containsKey(name, OPERATOR_CHARS.length + 1, name.length - (OPERATOR_CHARS.length+1));
}
}
return false;
}