1
0
Fork 0
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:
Marc-Andre Laperle 2024-02-02 11:39:16 -05:00 committed by GitHub
parent f3c2d91dfa
commit e838a231d9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 170 additions and 4 deletions

View file

@ -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 {};
//

View file

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

View file

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