diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index 4f8e8145382..6dd6e1d89c7 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -8937,4 +8937,23 @@ public class AST2CPPTests extends AST2BaseTest { assertEquals(1, names.length); assertTrue(names[0].resolveBinding() instanceof ICPPConstructor); } + + // void g(char *); + // void f(char *); + // void f(const char *); + // void testa() { + // f("abc"); + // g("abc"); + // } + public void testRankingOfDeprecatedConversionOnStringLiteral() throws Exception { + String code= getAboveComment(); + BindingAssertionHelper bh= new BindingAssertionHelper(code, true); + IFunction g= bh.assertNonProblem("g(char *)", 1); + IFunction fconst= bh.assertNonProblem("f(const char *)", 1); + + IBinding ref= bh.assertNonProblem("f(\"abc\")", 1); + assertSame(fconst, ref); + ref= bh.assertNonProblem("g(\"abc\")", 1); + assertSame(g, ref); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java index 44dda707a70..8b38746480d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/Conversions.java @@ -480,8 +480,8 @@ public class Conversions { final IValue av= at.getSize(); final IValue sv= st.getSize(); if (av == sv || (av != null && av.equals(sv))) { - t= SemanticUtil.getNestedType(at.getType(), TDEF | REF); - s= SemanticUtil.getNestedType(st.getType(), TDEF | REF); + t= SemanticUtil.getNestedType(at.getType(), TDEF | REF | ALLCVQ); + s= SemanticUtil.getNestedType(st.getType(), TDEF | REF | ALLCVQ); } else { return -1; } @@ -797,7 +797,7 @@ public class Conversions { */ private static final boolean lvalue_to_rvalue(final Cost cost) { IType target = getNestedType(cost.target, REF | TDEF | ALLCVQ); - IType source= getNestedType(cost.source, REF | TDEF | ALLCVQ); + IType source= getNestedType(cost.source, REF | TDEF); // 4.2 array to pointer conversion if (source instanceof IArrayType) { @@ -826,15 +826,14 @@ public class Conversions { } } } - if (!isConverted && (target instanceof IPointerType || target instanceof IBasicType)) { + if (!isConverted) { source = new CPPPointerType(getNestedType(arrayType.getType(), TDEF)); } - } else if (target instanceof IPointerType) { + } else if (source instanceof IFunctionType) { // 4.3 function to pointer conversion - final IType targetPtrTgt= getNestedType(((IPointerType) target).getType(), TDEF); - if (targetPtrTgt instanceof IFunctionType && source instanceof IFunctionType) { - source = new CPPPointerType(source); - } + source = new CPPPointerType(source); + } else { + source = getNestedType(source, TDEF | REF | ALLCVQ); } if (source == null || target == null) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java index a9748f636d3..5316adf3402 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/TemplateArgumentDeduction.java @@ -188,7 +188,6 @@ public class TemplateArgumentDeduction { boolean isDependentPar= CPPTemplates.isDependentType(par); if (checkExactMatch || isDependentPar) { - boolean isReferenceTypeParameter= false; IType arg = fnArgs[j]; par= SemanticUtil.getNestedType(par, SemanticUtil.TDEF); // adjustParameterType preserves typedefs @@ -200,9 +199,11 @@ public class TemplateArgumentDeduction { // Check if this is a deduced context IType inner= Conversions.getInitListType(par); if (inner != null) { - IType[] types = ((InitializerListType) arg).getExpressionTypes(); - for (IType iType : types) { - if (!deduct.fromType(inner, iType, false)) + final InitializerListType initListType = (InitializerListType) arg; + IType[] types = initListType.getExpressionTypes(); + ValueCategory[] valueCats = initListType.getValueCategories(); + for (int i = 0; i < types.length; i++) { + if (!deduceFromFunctionArg(inner, types[i], valueCats[i], checkExactMatch, isDependentPar, deduct)) return false; } } @@ -210,71 +211,10 @@ public class TemplateArgumentDeduction { } // 14.8.2.1-2 - if (par instanceof ICPPReferenceType) { - // If P is an rvalue reference to a cv-unqualified template parameter and the argument is an - // lvalue, the type "lvalue reference to A" is used in place of A for type deduction. - isReferenceTypeParameter= true; - final ICPPReferenceType refPar = (ICPPReferenceType) par; - if (refPar.isRValueReference() && refPar.getType() instanceof ICPPTemplateParameter && - argIsLValue != null && argIsLValue[j] == LVALUE) { - arg= new CPPReferenceType(getSimplifiedType(arg), false); - } else { - arg= getArgumentTypeForDeduction(arg, true); - } - par= SemanticUtil.getNestedType(par, SemanticUtil.REF | SemanticUtil.TDEF); - } else { - arg= getArgumentTypeForDeduction(arg, false); - } - - if (!checkExactMatch) { - // 14.8.2.1-3 - CVQualifier cvPar= SemanticUtil.getCVQualifier(par); - CVQualifier cvArg= SemanticUtil.getCVQualifier(arg); - if (cvPar == cvArg || (isReferenceTypeParameter && cvPar.isAtLeastAsQualifiedAs(cvArg))) { - IType pcheck= SemanticUtil.getNestedType(par, CVTYPE); - if (!(pcheck instanceof ICPPTemplateParameter)) { - par= pcheck; - arg= SemanticUtil.getNestedType(arg, CVTYPE); - IType argcheck= arg; - if (par instanceof IPointerType && arg instanceof IPointerType) { - pcheck= ((IPointerType) par).getType(); - argcheck= ((IPointerType) arg).getType(); - if (pcheck instanceof ICPPTemplateParameter) { - pcheck= null; - } else { - cvPar= SemanticUtil.getCVQualifier(pcheck); - cvArg= SemanticUtil.getCVQualifier(argcheck); - if (cvPar.isAtLeastAsQualifiedAs(cvArg)) { - pcheck= SemanticUtil.getNestedType(pcheck, CVTYPE); - argcheck= SemanticUtil.getNestedType(argcheck, CVTYPE); - } else { - pcheck= null; - } - } - } - if (pcheck instanceof ICPPTemplateInstance && argcheck instanceof ICPPClassType) { - ICPPTemplateInstance pInst = (ICPPTemplateInstance) pcheck; - ICPPClassTemplate pTemplate= getPrimaryTemplate(pInst); - if (pTemplate != null) { - ICPPClassType aInst= findBaseInstance((ICPPClassType) argcheck, pTemplate, CPPSemantics.MAX_INHERITANCE_DEPTH); - if (aInst != null && aInst != argcheck) { - par= pcheck; - arg= aInst; - } - } - } - } - } - } - - if (isDependentPar && !deduct.fromType(par, arg, true)) { + ValueCategory cat= argIsLValue != null ? argIsLValue[j] : LVALUE; + if (!deduceFromFunctionArg(par, arg, cat, checkExactMatch, isDependentPar, deduct)) { return false; } - if (checkExactMatch) { - IType instantiated= CPPTemplates.instantiateType(par, deduct.fDeducedArgs, deduct.fPackOffset, null); - if (!instantiated.isSameType(arg)) - return false; - } } } // Bug 309564: For partial ordering not all arguments need to be deduced @@ -290,6 +230,76 @@ public class TemplateArgumentDeduction { return false; } + private static boolean deduceFromFunctionArg(IType par, IType arg, ValueCategory valueCat, boolean checkExactMatch, boolean isDependentPar, TemplateArgumentDeduction deduct) throws DOMException { + boolean isReferenceTypeParameter= false; + if (par instanceof ICPPReferenceType) { + // If P is an rvalue reference to a cv-unqualified template parameter and the argument is an + // lvalue, the type "lvalue reference to A" is used in place of A for type deduction. + isReferenceTypeParameter= true; + final ICPPReferenceType refPar = (ICPPReferenceType) par; + if (refPar.isRValueReference() && refPar.getType() instanceof ICPPTemplateParameter && + valueCat == LVALUE) { + arg= new CPPReferenceType(getSimplifiedType(arg), false); + } else { + arg= getArgumentTypeForDeduction(arg, true); + } + par= SemanticUtil.getNestedType(par, REF | TDEF); + } else { + arg= getArgumentTypeForDeduction(arg, false); + } + + if (!checkExactMatch) { + // 14.8.2.1-3 + CVQualifier cvPar= SemanticUtil.getCVQualifier(par); + CVQualifier cvArg= SemanticUtil.getCVQualifier(arg); + if (cvPar == cvArg || (isReferenceTypeParameter && cvPar.isAtLeastAsQualifiedAs(cvArg))) { + IType pcheck= SemanticUtil.getNestedType(par, CVTYPE); + if (!(pcheck instanceof ICPPTemplateParameter)) { + par= pcheck; + arg= SemanticUtil.getNestedType(arg, CVTYPE); + IType argcheck= arg; + if (par instanceof IPointerType && arg instanceof IPointerType) { + pcheck= ((IPointerType) par).getType(); + argcheck= ((IPointerType) arg).getType(); + if (pcheck instanceof ICPPTemplateParameter) { + pcheck= null; + } else { + cvPar= SemanticUtil.getCVQualifier(pcheck); + cvArg= SemanticUtil.getCVQualifier(argcheck); + if (cvPar.isAtLeastAsQualifiedAs(cvArg)) { + pcheck= SemanticUtil.getNestedType(pcheck, CVTYPE); + argcheck= SemanticUtil.getNestedType(argcheck, CVTYPE); + } else { + pcheck= null; + } + } + } + if (pcheck instanceof ICPPTemplateInstance && argcheck instanceof ICPPClassType) { + ICPPTemplateInstance pInst = (ICPPTemplateInstance) pcheck; + ICPPClassTemplate pTemplate= getPrimaryTemplate(pInst); + if (pTemplate != null) { + ICPPClassType aInst= findBaseInstance((ICPPClassType) argcheck, pTemplate, CPPSemantics.MAX_INHERITANCE_DEPTH); + if (aInst != null && aInst != argcheck) { + par= pcheck; + arg= aInst; + } + } + } + } + } + } + + if (isDependentPar && !deduct.fromType(par, arg, true)) { + return false; + } + if (checkExactMatch) { + IType instantiated= CPPTemplates.instantiateType(par, deduct.fDeducedArgs, deduct.fPackOffset, null); + if (!instantiated.isSameType(arg)) + return false; + } + return true; + } + /** * 14.8.2.1.3 If P is a class and has the form template-id, then A can be a derived class of the deduced A. * @throws DOMException