1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-04 14:55:41 +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 { public void testADLForTemplateSpecializations_Bug327069() throws Exception {
parseAndCheckBindings(); 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.ICPPUnknownClassType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownType; 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.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.Context;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions.UDCMode; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Conversions.UDCMode;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.Rank; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.Rank;
@ -2346,7 +2347,7 @@ public class CPPSemantics {
// Loop over all functions // Loop over all functions
List<FunctionCost> potentialCosts= null; List<FunctionCost> potentialCosts= null;
for (IFunction fn : fns) { for (ICPPFunction fn : fns) {
if (fn == null) if (fn == null)
continue; 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 { throws DOMException {
IType[] argTypes = data.getFunctionArgumentTypes(); IType[] argTypes = data.getFunctionArgumentTypes();
ValueCategory[] isLValue= data.getFunctionArgumentValueCategories(); ValueCategory[] isLValue= data.getFunctionArgumentValueCategories();
int skipArg= 0; int skipArg= 0;
final ICPPFunctionType ftype= (ICPPFunctionType) fn.getType(); final ICPPFunctionType ftype= fn.getType();
if (ftype == null) if (ftype == null)
return null; return null;
@ -2836,7 +2837,7 @@ public class CPPSemantics {
if (inst != null) { if (inst != null) {
int cmp= -1; int cmp= -1;
if (result != null) { if (result != null) {
cmp= CPPTemplates.orderFunctionTemplates(resultTemplate, template); cmp= CPPTemplates.orderFunctionTemplates(resultTemplate, template, TypeSelection.PARAMETERS_AND_RETURN_TYPE);
if (cmp == 0) if (cmp == 0)
cmp= compareByRelevance(tu, resultTemplate, template); 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_FAIL = -2;
private static final int PACK_SIZE_NOT_FOUND = Integer.MAX_VALUE; private static final int PACK_SIZE_NOT_FOUND = Integer.MAX_VALUE;
private static final ICPPFunction[] NO_FUNCTIONS = {}; 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>. * 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 // 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 { throws DOMException {
int s1 = compareSpecialization(f1, f2); int s1 = compareSpecialization(f1, f2, mode);
int s2 = compareSpecialization(f2, f1); int s2 = compareSpecialization(f2, f1, mode);
if (s1 == s2) if (s1 == s2)
return 0; return 0;
@ -1731,22 +1732,38 @@ public class CPPTemplates {
return arg; 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); ICPPFunction transF1 = transferFunctionTemplate(f1);
if (transF1 == null) if (transF1 == null)
return -1; return -1;
// mstodo use function-type, parameter-types or return type. final ICPPFunctionType ft2 = f2.getType();
IType[] pars= f2.getType().getParameterTypes(); final ICPPFunctionType transFt1 = transF1.getType();
IType[] args = transF1.getType().getParameterTypes(); IType[] pars;
boolean nonStaticMember1= isNonStaticMember(f1); IType[] args;
boolean nonStaticMember2= isNonStaticMember(f2); switch(mode) {
if (nonStaticMember1 != nonStaticMember2) { case RETURN_TYPE:
if (nonStaticMember1) { pars= new IType[] {ft2.getReturnType()};
args= addImplicitObjectType(args, (ICPPMethod) f1); args= new IType[] {transFt1.getReturnType()};
} else { break;
pars= addImplicitObjectType(pars, (ICPPMethod) f2); 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); return TemplateArgumentDeduction.deduceForPartialOrdering(f2.getTemplateParameters(), pars, args);
} }
@ -1760,16 +1777,21 @@ public class CPPTemplates {
if (ct != null) { if (ct != null) {
try { try {
ICPPFunctionType ft = f1.getType(); ICPPFunctionType ft = f1.getType();
IType[] result= new IType[types.length+1]; final CPPReferenceType t = new CPPReferenceType(addQualifiers(ct, ft.isConst(), ft.isVolatile()), false);
result[0]= new CPPReferenceType(addQualifiers(ct, ft.isConst(), ft.isVolatile()), false); return concat(t, types);
System.arraycopy(types, 0, result, 1, types.length);
return result;
} catch (DOMException e) { } catch (DOMException e) {
} }
} }
return types; 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, private static ICPPClassTemplatePartialSpecialization findPartialSpecialization(ICPPClassTemplate ct,
ICPPTemplateArgument[] args) throws DOMException { ICPPTemplateArgument[] args) throws DOMException {
ICPPClassTemplatePartialSpecialization[] pspecs = ct.getPartialSpecializations(); ICPPClassTemplatePartialSpecialization[] pspecs = ct.getPartialSpecializations();

View file

@ -10,6 +10,8 @@
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp.semantics; 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 static org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil.*;
import org.eclipse.cdt.core.dom.ast.DOMException; 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.IFunction;
import org.eclipse.cdt.core.dom.ast.IType; 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.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.ICPPFunctionTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization; 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; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.Cost.DeferredUDC;
/** /**
* Cost for the entire function call * Cost for the entire function call
*/ */
class FunctionCost { class FunctionCost {
private final IFunction fFunction; private final ICPPFunction fFunction;
private final Cost[] fCosts; private final Cost[] fCosts;
private final ValueCategory[] fValueCategories; private final ValueCategory[] fValueCategories;
private boolean fIsDirectCopyCtor; private boolean fIsDirectCopyCtor;
public FunctionCost(IFunction fn, int paramCount) { public FunctionCost(ICPPFunction fn, int paramCount) {
fFunction= fn; fFunction= fn;
fCosts= new Cost[paramCount]; fCosts= new Cost[paramCount];
fValueCategories= new ValueCategory[paramCount]; fValueCategories= new ValueCategory[paramCount];
} }
public FunctionCost(IFunction fn, Cost cost) { public FunctionCost(ICPPFunction fn, Cost cost) {
fFunction= fn; fFunction= fn;
fCosts= new Cost[] {cost}; fCosts= new Cost[] {cost};
fValueCategories= null; // no udc will be performed fValueCategories= null; // no udc will be performed
@ -57,7 +61,7 @@ class FunctionCost {
fValueCategories[idx]= valueCat; fValueCategories[idx]= valueCat;
} }
public IFunction getFunction() { public ICPPFunction getFunction() {
return fFunction; return fFunction;
} }
@ -155,7 +159,8 @@ class FunctionCost {
} else if (!isTemplate && otherIsTemplate) { } else if (!isTemplate && otherIsTemplate) {
haveBetter = true; haveBetter = true;
} else if (isTemplate && otherIsTemplate) { } 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) { if (order < 0) {
haveBetter= true; haveBetter= true;
} else if (order > 0) { } 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.ITypedef;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; 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.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.ICPPFunctionType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace; import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
@ -156,11 +157,13 @@ public class SemanticUtil {
* @param method * @param method
* @return true if the specified method is a conversion operator * @return true if the specified method is a conversion operator
*/ */
public static final boolean isConversionOperator(ICPPMethod method) { public static final boolean isConversionOperator(ICPPFunction method) {
final char[] name= method.getNameCharArray(); if (method instanceof ICPPMethod) {
if (name.length > OPERATOR_CHARS.length + 1 && name[OPERATOR_CHARS.length] == ' ' && final char[] name= method.getNameCharArray();
CharArrayUtils.equals(name, 0, OPERATOR_CHARS.length, OPERATOR_CHARS)) { if (name.length > OPERATOR_CHARS.length + 1 && name[OPERATOR_CHARS.length] == ' ' &&
return !cas.containsKey(name, OPERATOR_CHARS.length + 1, name.length - (OPERATOR_CHARS.length+1)); 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; return false;
} }