mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-24 09:25:31 +02:00
Bug 302412: Template argument deduction for initializer lists.
This commit is contained in:
parent
83736061cd
commit
477c241751
4 changed files with 85 additions and 7 deletions
|
@ -8118,12 +8118,14 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// namespace std {
|
||||
// template<typename T> class initializer_list;
|
||||
// }
|
||||
// void f(std::initializer_list<int>);
|
||||
// //void ff(std::initializer_list<str>);
|
||||
// struct str {
|
||||
// str(const char*);
|
||||
// };
|
||||
// struct A {
|
||||
// A(std::initializer_list<double>); // #1
|
||||
// A(std::initializer_list<const char*>); // #3
|
||||
// A(std::initializer_list<str>); // #3
|
||||
// };
|
||||
// void f(std::initializer_list<int>);
|
||||
// void g(A);
|
||||
// void test() {
|
||||
// f( {1,2,3} ); // OK: f(initializer_list<int>) identity conversion
|
||||
|
@ -8213,5 +8215,27 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
// not detected by CDT
|
||||
// bh.assertProblem("f( {1.0} )", 1);
|
||||
}
|
||||
|
||||
// namespace std {
|
||||
// template<typename T> class initializer_list;
|
||||
// }
|
||||
// void g(const double &);
|
||||
// void h(int);
|
||||
// void test() {
|
||||
// g({1}); // same conversion as int to double
|
||||
//
|
||||
// h( {'a'} ); // OK: same conversion as char to int
|
||||
// h( {1.0} ); // error: narrowing
|
||||
// h( { } ); // OK: identity conversion
|
||||
// }
|
||||
public void testListInitialization_302412e() throws Exception {
|
||||
String code= getAboveComment();
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
|
||||
// not detected by CDT
|
||||
// bh.assertProblem("g({1})", 1);
|
||||
bh.assertNonProblem("h( {'a'} )", 1);
|
||||
bh.assertProblem("h( {1.0} )", 1);
|
||||
bh.assertNonProblem("h( { } )", 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4876,4 +4876,25 @@ public class AST2TemplateTests extends AST2BaseTest {
|
|||
final String code= getAboveComment();
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
}
|
||||
|
||||
// namespace std {
|
||||
// template<typename T> class initializer_list;
|
||||
// }
|
||||
// template<class T> void f(std::initializer_list<T>);
|
||||
// template<class T> void g(T);
|
||||
// void test() {
|
||||
// f({1,2,3}); // T deduced to int
|
||||
// f({1,"asdf"}); // error: T deduced to both int and const char*
|
||||
// g({1,2,3}); // error: no argument deduced for T
|
||||
// }
|
||||
public void testTypeDeductForInitLists_302412() throws Exception {
|
||||
final String code= getAboveComment();
|
||||
BindingAssertionHelper bh= new BindingAssertionHelper(code, true);
|
||||
|
||||
ICPPTemplateInstance inst;
|
||||
inst= bh.assertNonProblem("f({1,2,3})", 1);
|
||||
assertEquals("<int>", ASTTypeUtil.getArgumentListString(inst.getTemplateArguments(), true));
|
||||
bh.assertProblem("f({1,\"asdf\"})", 1);
|
||||
bh.assertProblem("g({1,2,3})", 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,6 @@ import org.eclipse.cdt.core.dom.ast.IValue;
|
|||
import org.eclipse.cdt.core.dom.ast.IBasicType.Kind;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBasicType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
|
||||
|
@ -202,7 +201,7 @@ public class Conversions {
|
|||
if (!isImpliedObjectType) {
|
||||
if (isReferenceRelated(T1, T2) < 0 || compareQualifications(cv1T1, cv2T2) >= 0) {
|
||||
Cost cost= nonReferenceConversion(exprIsLValue, cv2T2, T1, udc, false);
|
||||
if (!isImplicitWithoutRefQualifier) {
|
||||
if (!isImplicitWithoutRefQualifier && cost.converts()) {
|
||||
cost.setReferenceBinding(isLValueRef ? ReferenceBinding.LVALUE_REF : ReferenceBinding.RVALUE_REF_BINDS_RVALUE);
|
||||
}
|
||||
return cost;
|
||||
|
@ -322,11 +321,27 @@ public class Conversions {
|
|||
}
|
||||
return checkUserDefinedConversionSequence(false, arg, target, udc == UDCMode.deferUDC);
|
||||
}
|
||||
|
||||
IASTInitializerClause[] args = arg.getInitializerList().getClauses();
|
||||
if (args.length == 1) {
|
||||
final IASTInitializerClause firstArg = args[0];
|
||||
if (firstArg instanceof IASTExpression) {
|
||||
IASTExpression expr= (IASTExpression) firstArg;
|
||||
Cost cost= checkImplicitConversionSequence(target, expr.getExpressionType(), expr.isLValue(), udc, false);
|
||||
if (cost.isNarrowingConversion()) {
|
||||
return Cost.NO_CONVERSION;
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
} else if (args.length == 0) {
|
||||
return new Cost(arg, target, Rank.IDENTITY);
|
||||
}
|
||||
|
||||
return Cost.NO_CONVERSION;
|
||||
}
|
||||
|
||||
private static IType getInitListType(IType target) throws DOMException {
|
||||
if (target instanceof ICPPClassSpecialization && target instanceof ICPPTemplateInstance) {
|
||||
static IType getInitListType(IType target) throws DOMException {
|
||||
if (target instanceof ICPPClassType && target instanceof ICPPTemplateInstance) {
|
||||
ICPPTemplateInstance inst = (ICPPTemplateInstance) target;
|
||||
if (CharArrayUtils.equals(INITIALIZER_LIST_NAME, inst.getNameCharArray())) {
|
||||
IBinding owner = inst.getOwner();
|
||||
|
|
|
@ -190,6 +190,24 @@ public class TemplateArgumentDeduction {
|
|||
boolean isReferenceTypeParameter= false;
|
||||
IType arg = fnArgs[j];
|
||||
par= SemanticUtil.getNestedType(par, SemanticUtil.TDEF); // adjustParameterType preserves typedefs
|
||||
|
||||
// C++0x: 14.9.2.1-1
|
||||
if (arg instanceof InitializerListType) {
|
||||
assert !checkExactMatch;
|
||||
par= SemanticUtil.getNestedType(par, TDEF | REF | CVTYPE);
|
||||
|
||||
// Check if this is a deduced context
|
||||
IType inner= Conversions.getInitListType(par);
|
||||
if (inner != null) {
|
||||
IType[] types = ((InitializerListType) arg).getExpressionTypes();
|
||||
for (IType iType : types) {
|
||||
if (!deduct.fromType(inner, iType))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// 14.8.2.1-2
|
||||
if (par instanceof ICPPReferenceType) {
|
||||
// If P is an rvalue reference to a cv-unqualified template parameter and the argument is an
|
||||
|
|
Loading…
Add table
Reference in a new issue