From edca08b14f89cb17e24a005c6e14211ef860016b Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Tue, 27 Oct 2009 10:03:06 +0000 Subject: [PATCH] Special cases in argument deduction for function templates, bug 293409. --- .../parser/tests/ast2/AST2TemplateTests.java | 28 ++++++++++ .../eclipse/cdt/core/model/CoreModelUtil.java | 42 ++++++++------- .../parser/cpp/semantics/CPPTemplates.java | 53 +++++++++++++++---- .../dom/parser/cpp/semantics/Conversions.java | 2 +- 4 files changed, 95 insertions(+), 30 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 b516029160d..158fb0ec3bd 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 @@ -4183,4 +4183,32 @@ public class AST2TemplateTests extends AST2BaseTest { assertFalse(func instanceof ICPPUnknownBinding); bh.assertProblem("n();", 1); } + + // template struct CT {}; + // class D : public CT {}; + // template void f1(const CT &) {} + // template void f2(const CT *) {} + // template void f3(CT *) {} + // template void f4(volatile S*) {} + // void t() { + // D d; + // const volatile int *i= 0; + // const D cd= *new D(); + // f1(d); + // f2(&d); + // f2(&cd); + // f3(&d); + // f4(i); + // f3(&cd); // must be a problem, cd is const + // } + public void testArgumentDeduction_293409() throws Exception { + final String code = getAboveComment(); + BindingAssertionHelper bh= new BindingAssertionHelper(code, true); + bh.assertNonProblem("f1(d);", 2, ICPPFunction.class); + bh.assertNonProblem("f2(&d);", 2, ICPPFunction.class); + bh.assertNonProblem("f2(&cd);", 2, ICPPFunction.class); + bh.assertNonProblem("f3(&d);", 2, ICPPFunction.class); + bh.assertNonProblem("f4(i);", 2, ICPPFunction.class); + bh.assertProblem("f3(&cd);", 2); + } } diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/CoreModelUtil.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/CoreModelUtil.java index b663b462de3..2f0801a2f38 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/CoreModelUtil.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/core/model/CoreModelUtil.java @@ -550,31 +550,35 @@ public class CoreModelUtil { */ public static ITranslationUnit findTranslationUnitForLocation(IPath location, ICProject preferredProject) throws CModelException { IFile[] files= ResourceLookup.findFilesForLocation(location); + boolean oneExisting= false; if (files.length > 0) { for (IFile file : files) { - ITranslationUnit tu= findTranslationUnit(file); - if (tu != null) { - return tu; - } - } - } else { - CoreModel coreModel = CoreModel.getDefault(); - ITranslationUnit tu= null; - if (preferredProject != null) { - tu= coreModel.createTranslationUnitFrom(preferredProject, location); - } - if (tu == null) { - ICProject[] projects= coreModel.getCModel().getCProjects(); - for (int i = 0; i < projects.length && tu == null; i++) { - ICProject project = projects[i]; - if (!project.equals(preferredProject)) { - tu= coreModel.createTranslationUnitFrom(project, location); + if (file.exists()) { + oneExisting= true; + ITranslationUnit tu= findTranslationUnit(file); + if (tu != null) { + return tu; } } } - return tu; + if (oneExisting) + return null; + } + CoreModel coreModel = CoreModel.getDefault(); + ITranslationUnit tu= null; + if (preferredProject != null) { + tu= coreModel.createTranslationUnitFrom(preferredProject, location); } - return null; + if (tu == null) { + ICProject[] projects= coreModel.getCModel().getCProjects(); + for (int i = 0; i < projects.length && tu == null; i++) { + ICProject project = projects[i]; + if (!project.equals(preferredProject)) { + tu= coreModel.createTranslationUnitFrom(project, location); + } + } + } + return tu; } /** 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 f4972e71ab3..98feb51fb3a 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 @@ -1478,13 +1478,40 @@ public class CPPTemplates { par= getParameterTypeForDeduction(par, isReferenceType); // 14.8.2.1.3 - if (par instanceof ICPPTemplateInstance && !(par instanceof ICPPTemplateParameter) && arg instanceof ICPPClassType) { - ICPPTemplateInstance pInst = (ICPPTemplateInstance) par; - ICPPClassTemplate pTemplate= getPrimaryTemplate(pInst); - if (pTemplate != null) { - ICPPClassType aInst= findBaseInstance((ICPPClassType) arg, pTemplate, CPPSemantics.MAX_INHERITANCE_DEPTH); - if (aInst != null) { - arg= aInst; + int cvPar= Conversions.getCVQualifier(par); + int cvArg= Conversions.getCVQualifier(arg); + if (cvPar == cvArg || (isReferenceType && (cvArg & ~cvPar) == 0)) { + IType pcheck= SemanticUtil.getNestedType(par, SemanticUtil.CVQ | SemanticUtil.PTR_CVQ); + if (!(pcheck instanceof ICPPTemplateParameter)) { + par= pcheck; + arg= SemanticUtil.getNestedType(arg, SemanticUtil.CVQ | SemanticUtil.PTR_CVQ); + 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= Conversions.getCVQualifier(pcheck); + cvArg= Conversions.getCVQualifier(argcheck); + if ((cvArg & ~cvPar) == 0) { + pcheck= SemanticUtil.getNestedType(pcheck, SemanticUtil.CVQ); + argcheck= SemanticUtil.getNestedType(argcheck, SemanticUtil.CVQ); + } 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; + } + } } } } @@ -1637,10 +1664,16 @@ public class CPPTemplates { p = pa.getType(); a = aa.getType(); } else if (p instanceof IQualifierType) { - if (a instanceof IQualifierType) { - a = ((IQualifierType) a).getType(); //TODO a = strip qualifiers from p out of a + IType uqp = SemanticUtil.getNestedType(p, SemanticUtil.CVQ | SemanticUtil.PTR_CVQ); + IType uqa = SemanticUtil.getNestedType(a, SemanticUtil.CVQ | SemanticUtil.PTR_CVQ); + if (uqp instanceof ICPPTemplateParameter) { + int remaining= Conversions.getCVQualifier(a) & ~Conversions.getCVQualifier(p); + if (remaining != 0) { + uqa= SemanticUtil.addQualifiers(uqa, (remaining & 1) != 0, (remaining & 2) != 0); + } } - p = ((IQualifierType) p).getType(); + a= uqa; + p= uqp; } else if (p instanceof IFunctionType) { if (!(a instanceof IFunctionType)) return false; 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 ef202c64ccf..131cd1f0bd6 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 @@ -235,7 +235,7 @@ public class Conversions { /** * Returns 0 for no qualifier, 1 for const, 2 for volatile and 3 for const volatile. */ - private static int getCVQualifier(IType t) { + static int getCVQualifier(IType t) { if (t instanceof IQualifierType) { int result= 0; IQualifierType qt= (IQualifierType) t;