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:
parent
08367b0204
commit
7f63bc2647
5 changed files with 87 additions and 33 deletions
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue