mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 14:42:11 +02:00
Bug 509255 - Unresolved symbol due to invalid selection of template
specialization Change-Id: I130219f4ec7c3339b449d5c1af8a35150362613b
This commit is contained in:
parent
f247b3141c
commit
a8872762d0
2 changed files with 125 additions and 15 deletions
|
@ -2631,6 +2631,107 @@ public class AST2TemplateTests extends AST2TestBase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// template<typename T>
|
||||||
|
// struct A { typedef char type; };
|
||||||
|
//
|
||||||
|
// template <typename T, typename U>
|
||||||
|
// struct B { typedef int type; };
|
||||||
|
//
|
||||||
|
// template <typename T>
|
||||||
|
// struct B<T, typename A<T>::type> {};
|
||||||
|
//
|
||||||
|
// typename B<A<int>, int>::type a;
|
||||||
|
public void testSpecializationSelection_509255a() throws Exception {
|
||||||
|
parseAndCheckBindings();
|
||||||
|
}
|
||||||
|
|
||||||
|
// template <typename T>
|
||||||
|
// struct A {
|
||||||
|
// typedef T type;
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// template <typename T>
|
||||||
|
// void waldo(T t, typename T::type u);
|
||||||
|
//
|
||||||
|
// void test() {
|
||||||
|
// A<char> a;
|
||||||
|
// waldo(a, 1);
|
||||||
|
// }
|
||||||
|
public void testSpecializationSelection_509255b() throws Exception {
|
||||||
|
parseAndCheckBindings();
|
||||||
|
}
|
||||||
|
|
||||||
|
// struct true_type {
|
||||||
|
// static constexpr bool v = true;
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// struct false_type {
|
||||||
|
// static constexpr bool v = false;
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// template<typename T>
|
||||||
|
// T d();
|
||||||
|
//
|
||||||
|
// template<typename T, typename U>
|
||||||
|
// struct E : public true_type {};
|
||||||
|
//
|
||||||
|
// template<bool, typename T = void>
|
||||||
|
// struct enable_if {};
|
||||||
|
//
|
||||||
|
// template<typename T>
|
||||||
|
// struct enable_if<true, T> {
|
||||||
|
// typedef T type;
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// template <typename T>
|
||||||
|
// struct D {
|
||||||
|
// template <typename F>
|
||||||
|
// struct S;
|
||||||
|
//
|
||||||
|
// template <typename R, typename U>
|
||||||
|
// struct S<R(U::*)()> {
|
||||||
|
// using type = R();
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// using type = typename S<decltype(&T::m)>::type;
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// template <typename F, typename S, typename T = void>
|
||||||
|
// struct C : false_type {};
|
||||||
|
//
|
||||||
|
// template <typename F, typename R, typename... U>
|
||||||
|
// struct C<
|
||||||
|
// F, R(U...),
|
||||||
|
// typename enable_if<E<decltype(d<F>()(d<U>()...)), R>::v>::type>
|
||||||
|
// : true_type {};
|
||||||
|
//
|
||||||
|
// template <typename F, typename S>
|
||||||
|
// constexpr bool g() { return C<F, S>::v; }
|
||||||
|
//
|
||||||
|
// template <typename F>
|
||||||
|
// struct B {
|
||||||
|
// template <
|
||||||
|
// typename T,
|
||||||
|
// typename = typename enable_if<g<F, typename D<T>::type>()>::type>
|
||||||
|
// operator T*();
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// template <typename F>
|
||||||
|
// B<F> f(F p);
|
||||||
|
//
|
||||||
|
// struct A {
|
||||||
|
// void m();
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// void waldo(A* a);
|
||||||
|
//
|
||||||
|
// void test() {
|
||||||
|
// waldo(f([]() {}));
|
||||||
|
// }
|
||||||
|
public void testSpecializationSelection_509255c() throws Exception {
|
||||||
|
parseAndCheckBindings();
|
||||||
|
}
|
||||||
|
|
||||||
// template<typename _Tp>
|
// template<typename _Tp>
|
||||||
// class A {
|
// class A {
|
||||||
// public:
|
// public:
|
||||||
|
@ -9856,6 +9957,6 @@ public class AST2TemplateTests extends AST2TestBase {
|
||||||
public void testOOM_508254() throws Exception {
|
public void testOOM_508254() throws Exception {
|
||||||
BindingAssertionHelper helper = getAssertionHelper();
|
BindingAssertionHelper helper = getAssertionHelper();
|
||||||
// Just check that resolution does not throw an exception.
|
// Just check that resolution does not throw an exception.
|
||||||
helper.findName("waldo", 5).resolveBinding();
|
helper.findName("waldo").resolveBinding();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -205,8 +205,7 @@ public class TemplateArgumentDeduction {
|
||||||
IType type1 = ((ICPPTemplateNonTypeParameter) tpar).getType();
|
IType type1 = ((ICPPTemplateNonTypeParameter) tpar).getType();
|
||||||
type1= CPPTemplates.instantiateType(type1, new InstantiationContext(map, point));
|
type1= CPPTemplates.instantiateType(type1, new InstantiationContext(map, point));
|
||||||
IType type2= arg.getTypeOfNonTypeValue();
|
IType type2= arg.getTypeOfNonTypeValue();
|
||||||
// Template-argument deduced from an array bound may be of any integral
|
// Template-argument deduced from an array bound may be of any integral type.
|
||||||
// type.
|
|
||||||
if (type2 instanceof TypeOfValueDeducedFromArraySize && isIntegralType(type1)) {
|
if (type2 instanceof TypeOfValueDeducedFromArraySize && isIntegralType(type1)) {
|
||||||
IValue value = isBooleanType(type1) ? IntegralValue.create(true) : arg.getNonTypeValue();
|
IValue value = isBooleanType(type1) ? IntegralValue.create(true) : arg.getNonTypeValue();
|
||||||
arg = new CPPTemplateNonTypeArgument(value, type1);
|
arg = new CPPTemplateNonTypeArgument(value, type1);
|
||||||
|
@ -310,7 +309,7 @@ public class TemplateArgumentDeduction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return deduct.fromType(par, arg, true, point);
|
return deduct.fromType(par, arg, true, false, point);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -337,7 +336,7 @@ public class TemplateArgumentDeduction {
|
||||||
TemplateArgumentDeduction deduct=
|
TemplateArgumentDeduction deduct=
|
||||||
new TemplateArgumentDeduction(tmplParams, map, new CPPTemplateParameterMap(tmplParams.length), 0);
|
new TemplateArgumentDeduction(tmplParams, map, new CPPTemplateParameterMap(tmplParams.length), 0);
|
||||||
par= SemanticUtil.getNestedType(par, SemanticUtil.TDEF);
|
par= SemanticUtil.getNestedType(par, SemanticUtil.TDEF);
|
||||||
if (arg != null && !deduct.fromType(par, arg, false, point))
|
if (arg != null && !deduct.fromType(par, arg, false, false, point))
|
||||||
return null;
|
return null;
|
||||||
if (!map.addDeducedArgs(deduct.fDeducedArgs))
|
if (!map.addDeducedArgs(deduct.fDeducedArgs))
|
||||||
return null;
|
return null;
|
||||||
|
@ -370,7 +369,7 @@ public class TemplateArgumentDeduction {
|
||||||
p= getArgumentTypeForDeduction(p, a instanceof ICPPReferenceType);
|
p= getArgumentTypeForDeduction(p, a instanceof ICPPReferenceType);
|
||||||
a= SemanticUtil.getNestedType(a, SemanticUtil.REF | SemanticUtil.TDEF);
|
a= SemanticUtil.getNestedType(a, SemanticUtil.REF | SemanticUtil.TDEF);
|
||||||
TemplateArgumentDeduction deduct= new TemplateArgumentDeduction(tmplParams, null, map, 0);
|
TemplateArgumentDeduction deduct= new TemplateArgumentDeduction(tmplParams, null, map, 0);
|
||||||
if (!deduct.fromType(p, a, true, point)) {
|
if (!deduct.fromType(p, a, true, false, point)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,7 +409,7 @@ public class TemplateArgumentDeduction {
|
||||||
|
|
||||||
TemplateArgumentDeduction deduct=
|
TemplateArgumentDeduction deduct=
|
||||||
new TemplateArgumentDeduction(tmplParams, map, new CPPTemplateParameterMap(tmplParams.length), 0);
|
new TemplateArgumentDeduction(tmplParams, map, new CPPTemplateParameterMap(tmplParams.length), 0);
|
||||||
if (!deduct.fromType(p, a, false, point)) {
|
if (!deduct.fromType(p, a, false, false, point)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -562,7 +561,7 @@ public class TemplateArgumentDeduction {
|
||||||
par= getNestedType(par, TDEF | REF | ALLCVQ);
|
par= getNestedType(par, TDEF | REF | ALLCVQ);
|
||||||
arg= getNestedType(arg, TDEF | REF | ALLCVQ);
|
arg= getNestedType(arg, TDEF | REF | ALLCVQ);
|
||||||
|
|
||||||
if (!deduct.fromType(par, arg, false, point))
|
if (!deduct.fromType(par, arg, false, false, point))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return isMoreCVQualified ? 1 : 0;
|
return isMoreCVQualified ? 1 : 0;
|
||||||
|
@ -838,12 +837,13 @@ public class TemplateArgumentDeduction {
|
||||||
|
|
||||||
// Try to deduce from the original argument type, but if it fails, fall back to the simplified
|
// Try to deduce from the original argument type, but if it fails, fall back to the simplified
|
||||||
// argument type.
|
// argument type.
|
||||||
return fromType(p.getTypeValue(), a.getOriginalTypeValue(), false, point)
|
return fromType(p.getTypeValue(), a.getOriginalTypeValue(), false, true, point)
|
||||||
|| (a.getTypeValue() != a.getOriginalTypeValue()
|
|| (a.getTypeValue() != a.getOriginalTypeValue()
|
||||||
&& fromType(p.getTypeValue(), a.getTypeValue(), false, point));
|
&& fromType(p.getTypeValue(), a.getTypeValue(), false, true, point));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean fromType(IType p, IType a, boolean allowCVQConversion, IASTNode point) throws DOMException {
|
private boolean fromType(IType p, IType a, boolean allowCVQConversion, boolean verifyNonDeduced,
|
||||||
|
IASTNode point) throws DOMException {
|
||||||
IType originalArgType = a;
|
IType originalArgType = a;
|
||||||
a = SemanticUtil.getSimplifiedType(a);
|
a = SemanticUtil.getSimplifiedType(a);
|
||||||
while (p != null) {
|
while (p != null) {
|
||||||
|
@ -860,7 +860,7 @@ public class TemplateArgumentDeduction {
|
||||||
final ICPPPointerToMemberType ptrA = (ICPPPointerToMemberType) a;
|
final ICPPPointerToMemberType ptrA = (ICPPPointerToMemberType) a;
|
||||||
if (!allowCVQConversion && (ptrP.isConst() != ptrA.isConst() || ptrP.isVolatile() != ptrA.isVolatile()))
|
if (!allowCVQConversion && (ptrP.isConst() != ptrA.isConst() || ptrP.isVolatile() != ptrA.isVolatile()))
|
||||||
return false;
|
return false;
|
||||||
if (!fromType(ptrP.getMemberOfClass(), ptrA.getMemberOfClass(), false, point)) {
|
if (!fromType(ptrP.getMemberOfClass(), ptrA.getMemberOfClass(), false, false, point)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
p = ptrP.getType();
|
p = ptrP.getType();
|
||||||
|
@ -980,7 +980,16 @@ public class TemplateArgumentDeduction {
|
||||||
return false;
|
return false;
|
||||||
return fromTemplateInstance((ICPPTemplateInstance) p, (ICPPTemplateInstance) a, point);
|
return fromTemplateInstance((ICPPTemplateInstance) p, (ICPPTemplateInstance) a, point);
|
||||||
} else if (p instanceof ICPPUnknownBinding) {
|
} else if (p instanceof ICPPUnknownBinding) {
|
||||||
return true; // An unknown type may match anything.
|
if (!verifyNonDeduced)
|
||||||
|
return true; // An unknown type may match anything.
|
||||||
|
|
||||||
|
// Verify that the resolved binding matches the argument type.
|
||||||
|
InstantiationContext context = new InstantiationContext(fDeducedArgs, point);
|
||||||
|
IBinding binding = CPPTemplates.resolveUnknown((ICPPUnknownBinding) p, context);
|
||||||
|
if (binding instanceof ICPPUnknownBinding)
|
||||||
|
return true; // An unknown type may match anything.
|
||||||
|
|
||||||
|
return binding instanceof IType && ((IType) binding).isSameType(a);
|
||||||
} else {
|
} else {
|
||||||
return p.isSameType(a);
|
return p.isSameType(a);
|
||||||
}
|
}
|
||||||
|
@ -1065,7 +1074,7 @@ public class TemplateArgumentDeduction {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fromType(ftp.getReturnType(), fta.getReturnType(), false, point))
|
if (!fromType(ftp.getReturnType(), fta.getReturnType(), false, false, point))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
IType[] pParams = ftp.getParameterTypes();
|
IType[] pParams = ftp.getParameterTypes();
|
||||||
|
@ -1103,7 +1112,7 @@ public class TemplateArgumentDeduction {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!deduct.fromType(p, aParams[i], false, point))
|
if (!deduct.fromType(p, aParams[i], false, true, point))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Add table
Reference in a new issue