From 4f634fd92354f5576b22662908c429c65438f53c Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Tue, 28 Apr 2009 15:52:25 +0000 Subject: [PATCH] Argument deduction from class instances, bug 272848. --- .../tests/ast2/AST2CPPSpecFailingTest.java | 51 ---------- .../parser/tests/ast2/AST2CPPSpecTest.java | 15 +++ .../parser/tests/ast2/AST2TemplateTests.java | 2 +- .../parser/tests/ast2/DOMParserTestSuite.java | 1 - .../parser/cpp/semantics/CPPTemplates.java | 94 ++++++++++++++----- .../lrparser/tests/LRCPPSpecFailingTest.java | 66 ------------- .../lrparser/tests/LRParserTestSuite.java | 1 - 7 files changed, 88 insertions(+), 142 deletions(-) delete mode 100644 core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecFailingTest.java delete mode 100644 lrparser/org.eclipse.cdt.core.lrparser.tests/src/org/eclipse/cdt/core/lrparser/tests/LRCPPSpecFailingTest.java diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecFailingTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecFailingTest.java deleted file mode 100644 index 5bc52cf4bb8..00000000000 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecFailingTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2005, 2008 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Devin Steffler (IBM Corporation) - initial API and implementation - * Markus Schorn (Wind River Systems) - *******************************************************************************/ -package org.eclipse.cdt.core.parser.tests.ast2; - -import junit.framework.TestSuite; - -import org.eclipse.cdt.core.parser.ParserLanguage; - -/** - * NOTE: Once these tests pass (are fixed) then fix the test to work so that they - * are tested for a pass instead of a failure and move them to AST2CPPSpecTest.java. - */ -public class AST2CPPSpecFailingTest extends AST2SpecBaseTest { - - public AST2CPPSpecFailingTest() { - } - - public AST2CPPSpecFailingTest(String name) { - super(name); - } - - public static TestSuite suite() { - return suite(AST2CPPSpecFailingTest.class); - } - - public void testDummy() {} // avoids JUnit "no tests" warning - - // template struct B { }; - // template struct D : public B {}; - // struct D2 : public B {}; - // template void f(B&){} - // void t() - // { - // D d; - // D2 d2; - // f(d); //calls f(B&) - // f(d2); //calls f(B&) - // } - public void _test14_8_2_4s8() throws Exception { - parse(getAboveComment(), ParserLanguage.CPP, true, 0); - } -} diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java index 371603af86d..3569d6f5c47 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPSpecTest.java @@ -5691,6 +5691,21 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest { parse(getAboveComment(), ParserLanguage.CPP, true, 0); } + // template struct B { }; + // template struct D : public B {}; + // struct D2 : public B {}; + // template void f(B&){} + // void t() + // { + // D d; + // D2 d2; + // f(d); //calls f(B&) + // f(d2); //calls f(B&) + // } + public void test14_8_2_4s8() throws Exception { + parse(getAboveComment(), ParserLanguage.CPP, true, 0); + } + // template void f(double a[10][i]); // int v[10][20]; // int foo() { 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 3a7dd959bcd..0b643ed3391 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 @@ -2248,7 +2248,7 @@ public class AST2TemplateTests extends AST2BaseTest { // void test(A p) { // f(p); // } - public void _testFunctionTemplate_272848() throws Exception { + public void testFunctionTemplate_272848() throws Exception { final String code = getAboveComment(); parseAndCheckBindings(code, ParserLanguage.CPP); } diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java index 624f0dbf075..ef0874d5b5c 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java @@ -42,7 +42,6 @@ public class DOMParserTestSuite extends TestCase { suite.addTest(ASTNodeSelectorTest.suite()); suite.addTestSuite(CodeReaderCacheTest.class); suite.addTest(AST2CPPSpecTest.suite()); - suite.addTest(AST2CPPSpecFailingTest.suite()); suite.addTestSuite(AST2CSpecTest.class); suite.addTestSuite(DOMSelectionParseTest.class); suite.addTestSuite(GCCCompleteParseExtensionsTest.class); 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 1ef56db8acc..18887f57139 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 @@ -59,6 +59,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateParameter; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplatedTypeTemplateParameter; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate; @@ -1460,11 +1461,22 @@ public class CPPTemplates { if (isDependentType(par)) { par= SemanticUtil.getNestedType(par, SemanticUtil.TDEF); // adjustParameterType preserves typedefs par= SemanticUtil.adjustParameterType(par, false); - // 14.8.2.1.2 + // 14.8.2.1.2 and 14.8.2.1.3 final boolean isReferenceType = par instanceof ICPPReferenceType; - final IType arg= getArgumentTypeForDeduction(fnArgs[j], isReferenceType); + IType arg= getArgumentTypeForDeduction(fnArgs[j], isReferenceType); 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; + } + } + } if (!deduceTemplateParameterMap(par, arg, map)) { return false; } @@ -1625,29 +1637,34 @@ public class CPPTemplates { ICPPTemplateInstance pInst = (ICPPTemplateInstance) p; ICPPTemplateInstance aInst = (ICPPTemplateInstance) a; + ICPPClassTemplate pTemplate= getPrimaryTemplate(pInst); + ICPPClassTemplate aTemplate= getPrimaryTemplate(aInst); + if (pTemplate == null || aTemplate == null || !aTemplate.isSameType(pTemplate)) + return false; + ICPPTemplateArgument[] pArgs = pInst.getTemplateArguments(); - pArgs= pArgs == null ? ICPPTemplateArgument.EMPTY_ARGUMENTS : pArgs; // aftodo - unnecessary? + ICPPTemplateArgument[] aArgs = aInst.getTemplateArguments(); + if (pArgs.length > aArgs.length) + return false; - ICPPTemplateParameterMap aMap = aInst.getTemplateParameterMap(); - if (aMap != null && !(aInst.getTemplateDefinition() instanceof ICPPClassTemplatePartialSpecialization)) { - ICPPTemplateParameter[] aParams = aInst.getTemplateDefinition().getTemplateParameters(); - if (pArgs.length != aParams.length) - return false; - for (int i = 0; i < pArgs.length; i++) { - ICPPTemplateArgument t = aMap.getArgument(aParams[i]); - if (t == null || !deduceTemplateParameterMap(pArgs[i], t, map)) + ICPPTemplateParameter[] tpars= null; + for (int i = 0; i < aArgs.length; i++) { + ICPPTemplateArgument pArg; + if (i < pArgs.length) { + pArg= pArgs[i]; + } else { + if (tpars == null) { + tpars= pTemplate.getTemplateParameters(); + if (tpars.length < aArgs.length) + return false; + } + pArg= tpars[i].getDefaultValue(); + if (pArg == null) return false; + pArg= instantiateArgument(pArg, map, null); } - } else { - ICPPTemplateArgument[] aArgs = aInst.getTemplateArguments(); - aArgs= aArgs == null ? ICPPTemplateArgument.EMPTY_ARGUMENTS : aArgs; // aftodo - unnecessary? - - if (aArgs.length != pArgs.length) + if (!deduceTemplateParameterMap(pArg, aArgs[i], map)) return false; - for (int i = 0; i < pArgs.length; i++) { - if (!deduceTemplateParameterMap(pArgs[i], aArgs[i], map)) - return false; - } } return true; } else if (p instanceof ICPPUnknownBinding) { @@ -1660,6 +1677,40 @@ public class CPPTemplates { return false; } + /** + * 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 + */ + private static ICPPClassType findBaseInstance(ICPPClassType a, ICPPClassTemplate pTemplate, int maxdepth) throws DOMException { + if (a instanceof ICPPTemplateInstance) { + final ICPPTemplateInstance inst = (ICPPTemplateInstance) a; + ICPPClassTemplate tmpl= getPrimaryTemplate(inst); + if (pTemplate.isSameType(tmpl)) + return a; + } + if (maxdepth-- > 0) { + for (ICPPBase cppBase : a.getBases()) { + IBinding base= cppBase.getBaseClass(); + if (base instanceof ICPPClassType) { + final ICPPClassType inst= findBaseInstance((ICPPClassType) base, pTemplate, maxdepth); + if (inst != null) + return inst; + } + } + } + return null; + } + + private static ICPPClassTemplate getPrimaryTemplate(ICPPTemplateInstance inst) throws DOMException { + ICPPTemplateDefinition template= inst.getTemplateDefinition(); + if (template instanceof ICPPClassTemplatePartialSpecialization) { + return ((ICPPClassTemplatePartialSpecialization) template).getPrimaryClassTemplate(); + } else if (template instanceof ICPPClassTemplate) { + return (ICPPClassTemplate) template; + } + return null; + } + /** * Transforms a function template for use in partial ordering, as described in the * spec 14.5.5.2-3 @@ -1863,8 +1914,7 @@ public class CPPTemplates { */ static private ICPPFunctionTemplate classTemplateSpecializationToFunctionTemplate(ICPPClassTemplatePartialSpecialization specialization) { try { -// ICPPTemplateArgument[] args= specialization.getTemplateArguments(); - ICPPTemplateArgument[] args= (specialization).getTemplateArguments(); + ICPPTemplateArgument[] args= specialization.getTemplateArguments(); IBinding paramType = deferredInstance(specialization, args); if (!(paramType instanceof IType)) return null; diff --git a/lrparser/org.eclipse.cdt.core.lrparser.tests/src/org/eclipse/cdt/core/lrparser/tests/LRCPPSpecFailingTest.java b/lrparser/org.eclipse.cdt.core.lrparser.tests/src/org/eclipse/cdt/core/lrparser/tests/LRCPPSpecFailingTest.java deleted file mode 100644 index d659b54f7d2..00000000000 --- a/lrparser/org.eclipse.cdt.core.lrparser.tests/src/org/eclipse/cdt/core/lrparser/tests/LRCPPSpecFailingTest.java +++ /dev/null @@ -1,66 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2006, 2008 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.cdt.core.lrparser.tests; - -import junit.framework.TestSuite; - -import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; -import org.eclipse.cdt.core.dom.lrparser.gnu.GCCLanguage; -import org.eclipse.cdt.core.dom.lrparser.gnu.GPPLanguage; -import org.eclipse.cdt.core.model.ILanguage; -import org.eclipse.cdt.core.parser.ParserLanguage; -import org.eclipse.cdt.core.parser.tests.ast2.AST2CPPSpecFailingTest; -import org.eclipse.cdt.internal.core.parser.ParserException; - -@SuppressWarnings("restriction") -public class LRCPPSpecFailingTest extends AST2CPPSpecFailingTest { - - public static TestSuite suite() { - return suite(LRCPPSpecFailingTest.class); - } - - public LRCPPSpecFailingTest() { } - public LRCPPSpecFailingTest(String name) { super(name); } - - - @Override - protected void parseCandCPP( String code, boolean checkBindings, int expectedProblemBindings ) throws ParserException { - parse(code, ParserLanguage.C, checkBindings, expectedProblemBindings); - parse(code, ParserLanguage.CPP, checkBindings, expectedProblemBindings); - } - - @Override - protected IASTTranslationUnit parse( String code, ParserLanguage lang, boolean checkBindings, int expectedProblemBindings ) throws ParserException { - ILanguage language = lang.isCPP() ? getCPPLanguage() : getCLanguage(); - ParseHelper.Options options = new ParseHelper.Options(); - options.setCheckBindings(checkBindings); - options.setExpectedProblemBindings(expectedProblemBindings); - return ParseHelper.parse(code, language, options); - } - - @Override - protected IASTTranslationUnit parse(String code, ParserLanguage lang, String[] problems) throws ParserException { - ILanguage language = lang.isCPP() ? getCPPLanguage() : getCLanguage(); - ParseHelper.Options options = new ParseHelper.Options(); - options.setProblems(problems); - return ParseHelper.parse(code, language, options); - } - - - protected ILanguage getCLanguage() { - return GCCLanguage.getDefault(); - } - - protected ILanguage getCPPLanguage() { - return GPPLanguage.getDefault(); - } - -} diff --git a/lrparser/org.eclipse.cdt.core.lrparser.tests/src/org/eclipse/cdt/core/lrparser/tests/LRParserTestSuite.java b/lrparser/org.eclipse.cdt.core.lrparser.tests/src/org/eclipse/cdt/core/lrparser/tests/LRParserTestSuite.java index 2b3c05843cc..206aabc2be4 100644 --- a/lrparser/org.eclipse.cdt.core.lrparser.tests/src/org/eclipse/cdt/core/lrparser/tests/LRParserTestSuite.java +++ b/lrparser/org.eclipse.cdt.core.lrparser.tests/src/org/eclipse/cdt/core/lrparser/tests/LRParserTestSuite.java @@ -33,7 +33,6 @@ public class LRParserTestSuite extends TestSuite { addTest(LRCompleteParser2Tests.suite()); addTest(LRCompletionBasicTest.suite()); addTest(LRCompletionParseTest.suite()); - addTest(LRCPPSpecFailingTest.suite()); addTest(LRCPPSpecTest.suite()); addTest(LRCPPTests.suite()); addTest(LRCSpecTests.suite()); // a couple of failures