1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 22:52:11 +02:00

Bug 409094 - Incorrect partial ordering of function templates

Change-Id: Ia4e56f8662c93810776e88932d0a44358f7d5577
Reviewed-on: https://git.eclipse.org/r/13164
Reviewed-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
IP-Clean: Sergey Prigogin <eclipse.sprigogin@gmail.com>
Tested-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
This commit is contained in:
Nathan Ridge 2013-05-26 21:00:12 -04:00 committed by Sergey Prigogin
parent 22c6fd0c89
commit 57260c389d
2 changed files with 128 additions and 2 deletions

View file

@ -4503,10 +4503,57 @@ public class AST2TemplateTests extends AST2TestBase {
// int main() {
// foo(0);
// }
public void testFunctionTemplatePartialOrdering_388805() throws Exception {
public void testFunctionTemplateOrdering_388805() throws Exception {
parseAndCheckBindings();
}
// template <typename T>
// struct identity {
// typedef T type;
// };
//
// template <typename T>
// void foo(typename identity<T>::type);
//
// template <typename T>
// void foo(T);
//
// int main() {
// foo<int>(0); // ERROR HERE
// }
public void testFunctionTemplateOrdering_409094a() throws Exception {
parseAndCheckBindings();
}
// template <typename T>
// struct identity {
// typedef T type;
// };
//
// template <typename> struct W;
//
// template <typename T>
// struct A {
// typedef typename identity<T>::type type1;
// typedef W<type1> type2;
// };
//
// template<typename T>
// void foo(typename identity<T>::type);
//
// template <class T>
// void foo(T);
//
// struct waldo {};
//
// int main() {
// waldo w;
// foo<waldo>(w); // ERROR HERE
// }
public void testFunctionTemplateOrdering_409094b() throws Exception {
parseAndCheckBindings();
}
// template<typename T> class CT {};
// template<int I> class CTI {};
//

View file

@ -59,6 +59,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.internal.core.dom.parser.ITypeContainer;
import org.eclipse.cdt.internal.core.dom.parser.Value;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPPointerToMemberType;
@ -70,6 +71,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTemplateTypeArgument;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPUnknownMember;
/**
* Algorithms for deducing template arguments in various contexts.
@ -425,6 +427,7 @@ public class TemplateArgumentDeduction {
int result= 0;
TemplateArgumentDeduction deduct= new TemplateArgumentDeduction(tmplPars, new CPPTemplateParameterMap(0), new CPPTemplateParameterMap(fnParCount), 0);
IType fnParPack= null;
Set<Integer> usedTemplateParIds= new HashSet<Integer>();
for (int j= 0; j < fnArgCount; j++) {
IType par;
if (fnParPack != null) {
@ -445,18 +448,94 @@ public class TemplateArgumentDeduction {
}
IType arg = fnArgs[j];
addReferencedTemplateParameters(par, usedTemplateParIds);
int cmpSpecialized= deduceForPartialOrdering(par, arg, deduct, point);
if (cmpSpecialized < 0)
return cmpSpecialized;
if (cmpSpecialized > 0)
result= cmpSpecialized;
}
return result;
return verifyDeductionForPartialOrdering(tmplPars, usedTemplateParIds, deduct.fDeducedArgs) ? result : -1;
} catch (DOMException e) {
}
return -1;
}
private static void addReferencedTemplateParameters(IType t, Set<Integer> usedTemplateParIds) {
while (true) {
if (t instanceof ICPPTemplateParameter) {
usedTemplateParIds.add(((ICPPTemplateParameter) t).getParameterID());
return;
} else if (t instanceof ICPPFunctionType) {
final ICPPFunctionType ft = (ICPPFunctionType) t;
for (IType par : ft.getParameterTypes())
addReferencedTemplateParameters(par, usedTemplateParIds);
t = ft.getReturnType();
} else if (t instanceof ICPPPointerToMemberType) {
ICPPPointerToMemberType ptmt = (ICPPPointerToMemberType) t;
addReferencedTemplateParameters(ptmt.getMemberOfClass(), usedTemplateParIds);
t = ptmt.getType();
} else if (t instanceof ICPPTemplateInstance) {
ICPPTemplateInstance inst = (ICPPTemplateInstance) t;
for (ICPPTemplateArgument arg : inst.getTemplateArguments()) {
if (arg instanceof CPPTemplateTypeArgument)
addReferencedTemplateParameters(arg.getTypeValue(), usedTemplateParIds);
else
addReferencedTemplateParameters(arg.getNonTypeValue(), usedTemplateParIds);
}
if (inst.getTemplateDefinition() instanceof IType) {
t = (IType) inst.getTemplateDefinition();
} else {
return;
}
} else if (t instanceof ICPPUnknownMember) {
t = ((ICPPUnknownMember) t).getOwnerType();
} else if (t instanceof ITypeContainer) {
if (t instanceof IArrayType)
addReferencedTemplateParameters(((IArrayType) t).getSize(), usedTemplateParIds);
t = ((ITypeContainer) t).getType();
} else {
return;
}
}
}
private static void addReferencedTemplateParameters(IValue v, Set<Integer> usedTemplatePars) {
if (v != null && v.getEvaluation() instanceof EvalBinding) {
IBinding binding = ((EvalBinding) v.getEvaluation()).getBinding();
if (binding instanceof ICPPTemplateParameter) {
usedTemplatePars.add(((ICPPTemplateParameter) binding).getParameterID());
}
}
}
/**
* 14.8.2.4-11 [temp.deduction.partial]
* In most cases, all template parameters must have values in order for deduction to succeed,
* but for partial ordering purposes a template parameter may remain without a value provided
* it is not used in the types being used for partial ordering.
*/
private static boolean verifyDeductionForPartialOrdering(ICPPTemplateParameter[] pars,
Set<Integer> usedParIds, CPPTemplateParameterMap tpMap) {
for (ICPPTemplateParameter tpar : pars) {
if (usedParIds.contains(tpar.getParameterID())) {
if (tpar.isParameterPack()) {
ICPPTemplateArgument[] deducedArgs = tpMap.getPackExpansion(tpar);
if (deducedArgs != null) {
for (ICPPTemplateArgument arg : deducedArgs) {
if (arg == null)
return false;
}
}
} else {
if (tpMap.getArgument(tpar) == null)
return false;
}
}
}
return true;
}
private static int deduceForPartialOrdering(IType par, IType arg, TemplateArgumentDeduction deduct, IASTNode point) throws DOMException {
par= getNestedType(par, TDEF);
arg= getNestedType(arg, TDEF);