mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Partial fix for bug 574196/530103, error involving sizeof...() (#667)
Also discovered that non-type param is not handled at all. This case is not covered in this commit but there is a commented-out failing test for it.
This commit is contained in:
parent
f3c2d91dfa
commit
e838a231d9
3 changed files with 170 additions and 4 deletions
|
@ -9285,6 +9285,139 @@ public class AST2TemplateTests extends AST2CPPTestBase {
|
|||
assertSameType(CommonCPPTypes.int_, waldo);
|
||||
}
|
||||
|
||||
// template <int> struct foo;
|
||||
// template <> struct foo<2> { typedef int type; };
|
||||
//
|
||||
// template <typename... T>
|
||||
// using alias = typename foo<sizeof...(T)>::type;
|
||||
//
|
||||
// template <typename... U>
|
||||
// struct caller {
|
||||
// typedef alias<int, U...> type;
|
||||
// };
|
||||
//
|
||||
// template<typename caller<int>::type = 0>
|
||||
// void function() {
|
||||
// }
|
||||
//
|
||||
// int main() {
|
||||
// function<0>();
|
||||
// }
|
||||
public void testSizeofParameterPack_574196() throws Exception {
|
||||
parseAndCheckBindings();
|
||||
}
|
||||
|
||||
// template <int> struct foo;
|
||||
// template <> struct foo<3> { typedef int type; };
|
||||
//
|
||||
// template <typename... T>
|
||||
// using alias = typename foo<sizeof...(T)>::type;
|
||||
//
|
||||
// template <typename... U>
|
||||
// struct caller {
|
||||
// typedef alias<int,U..., U...> type;
|
||||
// };
|
||||
//
|
||||
// template<typename caller<int>::type = 0>
|
||||
// void function() {
|
||||
// }
|
||||
//
|
||||
// int main() {
|
||||
// function<0>();
|
||||
// }
|
||||
public void testSizeofParameterPack_574196_2() throws Exception {
|
||||
parseAndCheckBindings();
|
||||
}
|
||||
|
||||
// template <int> struct foo;
|
||||
// template <> struct foo<3> { typedef int type; };
|
||||
//
|
||||
// template <typename... T>
|
||||
// using alias = typename foo<sizeof...(T)>::type;
|
||||
//
|
||||
// template <typename... U>
|
||||
// struct caller {
|
||||
// typedef alias<U..., int, U...> type;
|
||||
// };
|
||||
//
|
||||
// template<typename caller<int>::type = 0>
|
||||
// void function() {
|
||||
// }
|
||||
//
|
||||
// int main() {
|
||||
// function<0>();
|
||||
// }
|
||||
public void testSizeofParameterPack_574196_3() throws Exception {
|
||||
parseAndCheckBindings();
|
||||
}
|
||||
|
||||
// template <int> struct foo;
|
||||
// template <> struct foo<2> { typedef int type; };
|
||||
//
|
||||
// template <typename V, typename... T>
|
||||
// using alias = typename foo<sizeof...(T)>::type;
|
||||
//
|
||||
// template <typename... U>
|
||||
// struct caller {
|
||||
// typedef alias<int, int, U...> type;
|
||||
// };
|
||||
//
|
||||
// template<typename caller<int>::type = 0>
|
||||
// void function() {
|
||||
// }
|
||||
//
|
||||
// int main() {
|
||||
// function<0>();
|
||||
// }
|
||||
public void testSizeofParameterPack_574196_4() throws Exception {
|
||||
parseAndCheckBindings();
|
||||
}
|
||||
|
||||
// template <int> struct foo;
|
||||
// template <> struct foo<2> { typedef int type; };
|
||||
//
|
||||
// template <typename V, int... T>
|
||||
// using myalias = typename foo<sizeof...(T)>::type;
|
||||
//
|
||||
// template <int... U>
|
||||
// struct caller {
|
||||
// typedef myalias<int, 0, U...> type;
|
||||
// };
|
||||
//
|
||||
// template<typename caller<0>::type = 4321>
|
||||
// void function() {
|
||||
// }
|
||||
//
|
||||
// int main() {
|
||||
// function<1234>();
|
||||
// }
|
||||
//TODO: Handle non-type parameter pack
|
||||
// public void testSizeofParameterPack_574196_5() throws Exception {
|
||||
// parseAndCheckBindings();
|
||||
// }
|
||||
|
||||
// template <int> struct foo;
|
||||
// template <> struct foo<0> { typedef int type; };
|
||||
//
|
||||
// template <typename V, typename... T>
|
||||
// using myalias = typename foo<sizeof...(T)>::type;
|
||||
//
|
||||
// template <typename... U>
|
||||
// struct caller {
|
||||
// typedef myalias<int, U...> type;
|
||||
// };
|
||||
//
|
||||
// template<typename caller<>::type = 4321>
|
||||
// void function() {
|
||||
// }
|
||||
//
|
||||
// int main() {
|
||||
// function<1234>();
|
||||
// }
|
||||
public void testSizeofParameterPack_574196_6() throws Exception {
|
||||
parseAndCheckBindings();
|
||||
}
|
||||
|
||||
// template <int, class>
|
||||
// struct A {};
|
||||
//
|
||||
|
|
|
@ -399,6 +399,11 @@ public class EvalUnary extends CPPDependentEvaluation {
|
|||
|
||||
@Override
|
||||
public ICPPEvaluation instantiate(InstantiationContext context, int maxDepth) {
|
||||
// if (fOperator == IASTUnaryExpression.op_sizeofParameterPack) {
|
||||
// //TODO: Something like EvalUnaryTypeID ?
|
||||
// return instantiateSizeofParameterPack(context);
|
||||
// }
|
||||
|
||||
if (fOperator == op_integerPack && context.getPackOffset() != -1) {
|
||||
return new EvalFixed(getType(), ValueCategory.PRVALUE, IntegralValue.create(context.getPackOffset()));
|
||||
}
|
||||
|
|
|
@ -44,11 +44,13 @@ import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_sizeofParamet
|
|||
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_typeid;
|
||||
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_typeof;
|
||||
|
||||
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||
import org.eclipse.cdt.core.dom.ast.IType;
|
||||
import org.eclipse.cdt.core.dom.ast.IValue;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
|
||||
|
@ -271,15 +273,15 @@ public class EvalUnaryTypeID extends CPPDependentEvaluation {
|
|||
return this;
|
||||
}
|
||||
int concreteArgCount = 0;
|
||||
boolean havePackExpansion = false;
|
||||
int packExpansionCount = 0;
|
||||
for (ICPPTemplateArgument arg : args) {
|
||||
if (arg.isPackExpansion()) {
|
||||
havePackExpansion = true;
|
||||
packExpansionCount++;
|
||||
} else {
|
||||
concreteArgCount++;
|
||||
}
|
||||
}
|
||||
if (havePackExpansion) {
|
||||
if (packExpansionCount > 0) {
|
||||
// TODO(bug 530103):
|
||||
// This will only handle correctly the case where there is a single argument
|
||||
// which is a pack expansion, and no concrete arguments.
|
||||
|
@ -291,7 +293,33 @@ public class EvalUnaryTypeID extends CPPDependentEvaluation {
|
|||
// sizeof...(P).
|
||||
// - Construct an EvalBinary tree representing the sum of |concreteArgCount|
|
||||
// and the EvalUnaryTypeIds from the previous step.
|
||||
return instantiateBySubstitution(context);
|
||||
|
||||
//malaperle: I implemented something that kind-of does what the comment
|
||||
//above suggest but am not confident enough that it covers all cases (hence the several instanceof checks).
|
||||
ICPPEvaluation packEval = null;
|
||||
for (ICPPTemplateArgument arg : args) {
|
||||
if (arg.isPackExpansion()) {
|
||||
if (arg.getTypeValue() instanceof ICPPParameterPackType) {
|
||||
ICPPParameterPackType parameterPackType = (ICPPParameterPackType) arg.getTypeValue();
|
||||
IType type = parameterPackType.getType();
|
||||
if (type instanceof ICPPTemplateParameter)
|
||||
packEval = new EvalUnaryTypeID(fOperator, type, getTemplateDefinition());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Can we really get here?
|
||||
if (packEval == null)
|
||||
return instantiateBySubstitution(context);
|
||||
|
||||
// For sizeof(...(T)), T={U..., U...}
|
||||
ICPPEvaluation multiPackCountEval = new EvalBinary(IASTBinaryExpression.op_multiply, packEval,
|
||||
new EvalFixed(getType(), getValueCategory(), IntegralValue.create(packExpansionCount)),
|
||||
pack);
|
||||
|
||||
return new EvalBinary(IASTBinaryExpression.op_plus, multiPackCountEval,
|
||||
new EvalFixed(getType(), getValueCategory(), IntegralValue.create(concreteArgCount)), pack);
|
||||
} else {
|
||||
return new EvalFixed(getType(), getValueCategory(), IntegralValue.create(concreteArgCount));
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue