1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-08 18:26:01 +02:00

Bug 527697 - Attempt deduction with all base classes of an argument type

Previously, we would only try the first base class whose primary
template matched that of the parameter type.

Change-Id: I0511e6a1ba1c7197887ff23bc37b70a2a820eb87
This commit is contained in:
Nathan Ridge 2017-12-06 23:59:37 -05:00
parent 58e2f34bfc
commit 6ef70ba044
2 changed files with 39 additions and 12 deletions

View file

@ -9053,6 +9053,22 @@ public class AST2TemplateTests extends AST2CPPTestBase {
ITypedef waldo = helper.assertNonProblem("Waldo");
assertSameType(CommonCPPTypes.int_, waldo);
}
// template <int, class>
// struct A {};
//
// struct B : A<0, int>, A<1, int> {};
//
// template <class T>
// void waldo(A<1, T>);
//
// void foo() {
// B b;
// waldo(b);
// }
public void testTemplateArgumentDeduction_MultipleInheritance_527697() throws Exception {
parseAndCheckBindings();
}
// template <typename T>
// struct A {};

View file

@ -58,6 +58,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateInstance;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateNonTypeParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateTemplateParameter;
import org.eclipse.cdt.core.parser.util.ArrayUtil;
import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
import org.eclipse.cdt.internal.core.dom.parser.IntegralValue;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
@ -301,10 +302,20 @@ public class TemplateArgumentDeduction {
ICPPTemplateInstance pInst = (ICPPTemplateInstance) pcheck;
ICPPClassTemplate pTemplate= getPrimaryTemplate(pInst);
if (pTemplate != null) {
ICPPClassType aInst= findBaseInstance((ICPPClassType) argcheck, pTemplate);
if (aInst != null && aInst != argcheck) {
par= pcheck;
arg= aInst;
ICPPClassType[] aInstances = findBaseInstances((ICPPClassType) argcheck, pTemplate);
boolean attempted = false;
for (ICPPClassType aInst : aInstances) {
if (aInst != null && aInst != argcheck) {
par= pcheck;
arg= aInst;
attempted = true;
if (deduct.fromType(par, arg, true, false)) {
return true;
}
}
}
if (attempted) {
return false;
}
}
}
@ -631,29 +642,29 @@ public class TemplateArgumentDeduction {
* 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.
*/
private static ICPPClassType findBaseInstance(ICPPClassType a, ICPPClassTemplate pTemplate) throws DOMException {
return findBaseInstance(a, pTemplate, CPPSemantics.MAX_INHERITANCE_DEPTH, new HashSet<>());
private static ICPPClassType[] findBaseInstances(ICPPClassType a, ICPPClassTemplate pTemplate) throws DOMException {
return findBaseInstances(a, pTemplate, CPPSemantics.MAX_INHERITANCE_DEPTH, new HashSet<>());
}
private static ICPPClassType findBaseInstance(ICPPClassType a, ICPPClassTemplate pTemplate, int maxdepth,
private static ICPPClassType[] findBaseInstances(ICPPClassType a, ICPPClassTemplate pTemplate, int maxdepth,
HashSet<Object> handled) throws DOMException {
if (a instanceof ICPPTemplateInstance) {
ICPPTemplateInstance inst = (ICPPTemplateInstance) a;
ICPPClassTemplate tmpl= getPrimaryTemplate(inst);
if (pTemplate.isSameType(tmpl))
return a;
return new ICPPClassType[] { a };
}
ICPPClassType[] results = ICPPClassType.EMPTY_CLASS_ARRAY;
if (maxdepth-- > 0) {
for (ICPPBase cppBase : a.getBases()) {
IBinding base= cppBase.getBaseClass();
if (base instanceof ICPPClassType && handled.add(base)) {
final ICPPClassType inst= findBaseInstance((ICPPClassType) base, pTemplate, maxdepth, handled);
if (inst != null)
return inst;
ICPPClassType[] inst= findBaseInstances((ICPPClassType) base, pTemplate, maxdepth, handled);
results = ArrayUtil.addAll(results, inst);
}
}
}
return null;
return ArrayUtil.trim(results);
}
private static ICPPClassTemplate getPrimaryTemplate(ICPPTemplateInstance inst) throws DOMException {