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 158fb0ec3bd..1e8adf1ace5 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 @@ -4211,4 +4211,20 @@ public class AST2TemplateTests extends AST2BaseTest { bh.assertNonProblem("f4(i);", 2, ICPPFunction.class); bh.assertProblem("f3(&cd);", 2); } + + // template struct C {}; + // template void f(T, C) {} + // template void f(T, C) {} + // + // void test() { + // char ch; + // C cint; + // C cchar; + // f(ch, cchar); + // f(ch, cint); + // } + public void testFunctionTemplateOrdering_293468() throws Exception { + final String code= getAboveComment(); + parseAndCheckBindings(code, ParserLanguage.CPP); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTTypeUtil.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTTypeUtil.java index 48bb8f91d56..31ac87a1ee4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTTypeUtil.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/ASTTypeUtil.java @@ -42,6 +42,7 @@ import org.eclipse.cdt.internal.core.dom.parser.c.CASTTypeId; import org.eclipse.cdt.internal.core.dom.parser.c.CVisitor; import org.eclipse.cdt.internal.core.dom.parser.c.ICInternalBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTypeId; +import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; @@ -246,6 +247,9 @@ public class ASTTypeUtil { result.append(Keywords.cpRBRACKET); } else if (type instanceof IBasicType) { IBasicType basicType= (IBasicType) type; + if (basicType.getModifiers() == CPPBasicType.UNIQUE_TYPE_QUALIFIER) { + return "@" + String.valueOf(basicType.hashCode()); //$NON-NLS-1$ + } final Kind kind = basicType.getKind(); if (basicType.isSigned()) { // 3.9.1.2: signed integer types diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBasicType.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBasicType.java index 31e2cab9a0c..7910901632f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBasicType.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPBasicType.java @@ -32,7 +32,7 @@ public class CPPBasicType implements ICPPBasicType { private IASTExpression fExpression; public CPPBasicType(Kind kind, int qualifiers, IASTExpression expression) { - if (kind == Kind.eUnspecified) { + if (kind == Kind.eUnspecified && qualifiers != UNIQUE_TYPE_QUALIFIER) { if ( (qualifiers & (IS_COMPLEX | IS_IMAGINARY)) != 0) { fKind= Kind.eFloat; } else if ( (qualifiers & (IS_LONG | IS_SHORT | IS_SIGNED | IS_UNSIGNED | IS_LONG_LONG)) != 0 ) { @@ -101,7 +101,7 @@ public class CPPBasicType implements ICPPBasicType { if (object == this) return true; - if (fModifiers == -1) + if (fModifiers == UNIQUE_TYPE_QUALIFIER) return false; if (object instanceof ITypedef || object instanceof IIndexType) 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 98feb51fb3a..46be86d7fd4 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 @@ -39,7 +39,6 @@ import org.eclipse.cdt.core.dom.ast.IEnumeration; import org.eclipse.cdt.core.dom.ast.IEnumerator; import org.eclipse.cdt.core.dom.ast.IFunction; import org.eclipse.cdt.core.dom.ast.IFunctionType; -import org.eclipse.cdt.core.dom.ast.IParameter; import org.eclipse.cdt.core.dom.ast.IPointerType; import org.eclipse.cdt.core.dom.ast.IProblemBinding; import org.eclipse.cdt.core.dom.ast.IQualifierType; @@ -111,13 +110,11 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPDeferredClassInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFieldSpecialization; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunctionInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunctionSpecialization; -import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunctionTemplate; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunctionTemplateSpecialization; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunctionType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPMethodInstance; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPMethodSpecialization; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPMethodTemplateSpecialization; -import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPParameter; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerToMemberType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateArgument; @@ -1794,9 +1791,8 @@ public class CPPTemplates { * for each occurrence of that parameter in the function parameter list * @throws DOMException */ - static private ICPPTemplateArgument[] createArgsForFunctionTemplateOrdering(ICPPFunctionTemplate template) + static private ICPPTemplateArgument[] createArgsForFunctionTemplateOrdering(ICPPTemplateParameter[] paramList) throws DOMException{ - ICPPTemplateParameter[] paramList = template.getTemplateParameters(); int size = paramList.length; ICPPTemplateArgument[] args = new ICPPTemplateArgument[size]; for (int i = 0; i < size; i++) { @@ -1812,51 +1808,54 @@ public class CPPTemplates { static protected int orderTemplateFunctions(ICPPFunctionTemplate f1, ICPPFunctionTemplate f2) throws DOMException { - // Using the transformed parameter list, perform argument deduction against the other - // function template - CPPTemplateParameterMap m1= new CPPTemplateParameterMap(2); - CPPTemplateParameterMap m2= new CPPTemplateParameterMap(2); - - ICPPTemplateArgument[] args = createArgsForFunctionTemplateOrdering(f1); - IBinding function = instantiateFunctionTemplate(f1, args); - if (function instanceof ICPPFunction) - if (!deduceTemplateParameterMapFromFunctionParameters(f2, ((ICPPFunction) function).getType().getParameterTypes(), m1)) - m1= null; - - args = createArgsForFunctionTemplateOrdering(f2); - function = instantiateFunctionTemplate(f2, args); - if (function instanceof ICPPFunction) - if (!deduceTemplateParameterMapFromFunctionParameters(f1, ((ICPPFunction) function).getType().getParameterTypes(), m2)) - m2= null; - - - // The transformed template is at least as specialized as the other iff the deduction - // succeeds and the deduced parameter types are an exact match. - // A template is more specialized than another iff it is at least as specialized as the + // 14.5.5.2 + // A template is more specialized than another if and only if it is at least as specialized as the // other template and that template is not at least as specialized as the first. - if (m1 == null) { - if (m2 == null) - return 0; - return -1; - } + boolean f1IsAtLeastAsSpecializedAsF2 = isAtLeastAsSpecializedAs(f1, f2); + boolean f2IsAtLeastAsSpecializedAsF1 = isAtLeastAsSpecializedAs(f2, f1); - if (m2 == null) + if (f1IsAtLeastAsSpecializedAsF2 == f2IsAtLeastAsSpecializedAsF1) + return 0; + + if (f1IsAtLeastAsSpecializedAsF2) return 1; - // Count the number of cv-qualifications. The function with a lower number - // of cv-qualifications is more specialized. - int d1 = 0; - for (ICPPTemplateArgument arg : m1.values()) { - if (arg.getTypeValue() instanceof IQualifierType) - d1++; + return -1; + } + + private static boolean isAtLeastAsSpecializedAs(ICPPFunctionTemplate f1, ICPPFunctionTemplate f2) throws DOMException { + // 14.5.5.2 + // Using the transformed parameter list, perform argument deduction against the other + // function template + // The transformed template is at least as specialized as the other if and only if the deduction + // succeeds and the deduced parameter types are an exact match. + ICPPTemplateArgument[] transferArgs = createArgsForFunctionTemplateOrdering(f1.getTemplateParameters()); + IBinding transferredTemplate = instantiateFunctionTemplate(f1, transferArgs); + if (!(transferredTemplate instanceof ICPPFunction)) + return false; + + CPPTemplateParameterMap map= new CPPTemplateParameterMap(2); + final IType[] transferredParameterTypes = ((ICPPFunction) transferredTemplate).getType().getParameterTypes(); + if (!deduceTemplateParameterMapFromFunctionParameters(f2, transferredParameterTypes, map)) + return false; + + final ICPPTemplateParameter[] tmplParams = f2.getTemplateParameters(); + for (ICPPTemplateParameter tmplParam : tmplParams) { + ICPPTemplateArgument deducedArg= map.getArgument(tmplParam); + if (deducedArg == null) + return false; } - int d2 = 0; - for (ICPPTemplateArgument arg : m2.values()) { - if (arg.getTypeValue() instanceof IQualifierType) { - d2++; - } + + // length can be different in case of varargs or default arguments + IType[] params= f2.getType().getParameterTypes(); + final int len= Math.min(params.length, transferredParameterTypes.length); + for (int i = 0; i