mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-23 17:05:26 +02:00
Argument deduction from class instances, bug 272848.
This commit is contained in:
parent
997f6d7197
commit
4f634fd923
7 changed files with 88 additions and 142 deletions
|
@ -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 <class T> struct B { };
|
||||
// template <class T> struct D : public B<T> {};
|
||||
// struct D2 : public B<int> {};
|
||||
// template <class T> void f(B<T>&){}
|
||||
// void t()
|
||||
// {
|
||||
// D<int> d;
|
||||
// D2 d2;
|
||||
// f(d); //calls f(B<int>&)
|
||||
// f(d2); //calls f(B<int>&)
|
||||
// }
|
||||
public void _test14_8_2_4s8() throws Exception {
|
||||
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
|
||||
}
|
||||
}
|
|
@ -5691,6 +5691,21 @@ public class AST2CPPSpecTest extends AST2SpecBaseTest {
|
|||
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
|
||||
}
|
||||
|
||||
// template <class T> struct B { };
|
||||
// template <class T> struct D : public B<T> {};
|
||||
// struct D2 : public B<int> {};
|
||||
// template <class T> void f(B<T>&){}
|
||||
// void t()
|
||||
// {
|
||||
// D<int> d;
|
||||
// D2 d2;
|
||||
// f(d); //calls f(B<int>&)
|
||||
// f(d2); //calls f(B<int>&)
|
||||
// }
|
||||
public void test14_8_2_4s8() throws Exception {
|
||||
parse(getAboveComment(), ParserLanguage.CPP, true, 0);
|
||||
}
|
||||
|
||||
// template<class T, T i> void f(double a[10][i]);
|
||||
// int v[10][20];
|
||||
// int foo() {
|
||||
|
|
|
@ -2248,7 +2248,7 @@ public class AST2TemplateTests extends AST2BaseTest {
|
|||
// void test(A<B> p) {
|
||||
// f(p);
|
||||
// }
|
||||
public void _testFunctionTemplate_272848() throws Exception {
|
||||
public void testFunctionTemplate_272848() throws Exception {
|
||||
final String code = getAboveComment();
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue