From 7f63bc26475f3ae8e62af653939fff58d2ca737e Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Fri, 8 Oct 2010 08:16:15 +0000 Subject: [PATCH] Bug 326900: Partial ordering of conversion-operators. --- .../parser/tests/ast2/AST2TemplateTests.java | 23 +++++++ .../parser/cpp/semantics/CPPSemantics.java | 9 +-- .../parser/cpp/semantics/CPPTemplates.java | 60 +++++++++++++------ .../parser/cpp/semantics/FunctionCost.java | 15 +++-- .../parser/cpp/semantics/SemanticUtil.java | 13 ++-- 5 files changed, 87 insertions(+), 33 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java index 9d97853113d..f7d6825e796 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java @@ -5113,4 +5113,27 @@ public class AST2TemplateTests extends AST2BaseTest { public void testADLForTemplateSpecializations_Bug327069() throws Exception { parseAndCheckBindings(); } + + // template T* f(V*); + // template T f(V*); + // template T* f(V); + // void x(int* (*) (int*)) { + // x(f); + // } + public void testPartialOrderingInNonCallContext_Bug326900() throws Exception { + parseAndCheckBindings(); + } + + // struct X { + // template operator T(); + // template operator T*(); + // }; + // void y(int *) { + // X x; + // y(x); + // } + public void testPartialOrderingForConversions_Bug326900() throws Exception { + parseAndCheckBindings(); + } + } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index 3a4f51e4386..f8d00892c58 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -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 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); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java index 5ccd79e3157..474d4db4ec4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPTemplates.java @@ -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 null. @@ -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(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionCost.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionCost.java index df6751d49bb..6d2c0e06e77 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionCost.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/FunctionCost.java @@ -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) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java index a40b35f607a..b7f5f15d7da 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/SemanticUtil.java @@ -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; }