1
0
Fork 0
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:
Sergey Prigogin 2016-12-19 17:19:34 -08:00 committed by Gerrit Code Review @ Eclipse.org
parent f247b3141c
commit a8872762d0
2 changed files with 125 additions and 15 deletions

View file

@ -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();
} }
} }

View file

@ -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;