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:
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 {
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue