Skip to content

Commit e838a23

Browse files
authored
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.
1 parent f3c2d91 commit e838a23

File tree

3 files changed

+170
-4
lines changed

3 files changed

+170
-4
lines changed

core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9285,6 +9285,139 @@ public void testSizeofParameterPack_527697() throws Exception {
92859285
assertSameType(CommonCPPTypes.int_, waldo);
92869286
}
92879287

9288+
// template <int> struct foo;
9289+
// template <> struct foo<2> { typedef int type; };
9290+
//
9291+
// template <typename... T>
9292+
// using alias = typename foo<sizeof...(T)>::type;
9293+
//
9294+
// template <typename... U>
9295+
// struct caller {
9296+
// typedef alias<int, U...> type;
9297+
// };
9298+
//
9299+
// template<typename caller<int>::type = 0>
9300+
// void function() {
9301+
// }
9302+
//
9303+
// int main() {
9304+
// function<0>();
9305+
// }
9306+
public void testSizeofParameterPack_574196() throws Exception {
9307+
parseAndCheckBindings();
9308+
}
9309+
9310+
// template <int> struct foo;
9311+
// template <> struct foo<3> { typedef int type; };
9312+
//
9313+
// template <typename... T>
9314+
// using alias = typename foo<sizeof...(T)>::type;
9315+
//
9316+
// template <typename... U>
9317+
// struct caller {
9318+
// typedef alias<int,U..., U...> type;
9319+
// };
9320+
//
9321+
// template<typename caller<int>::type = 0>
9322+
// void function() {
9323+
// }
9324+
//
9325+
// int main() {
9326+
// function<0>();
9327+
// }
9328+
public void testSizeofParameterPack_574196_2() throws Exception {
9329+
parseAndCheckBindings();
9330+
}
9331+
9332+
// template <int> struct foo;
9333+
// template <> struct foo<3> { typedef int type; };
9334+
//
9335+
// template <typename... T>
9336+
// using alias = typename foo<sizeof...(T)>::type;
9337+
//
9338+
// template <typename... U>
9339+
// struct caller {
9340+
// typedef alias<U..., int, U...> type;
9341+
// };
9342+
//
9343+
// template<typename caller<int>::type = 0>
9344+
// void function() {
9345+
// }
9346+
//
9347+
// int main() {
9348+
// function<0>();
9349+
// }
9350+
public void testSizeofParameterPack_574196_3() throws Exception {
9351+
parseAndCheckBindings();
9352+
}
9353+
9354+
// template <int> struct foo;
9355+
// template <> struct foo<2> { typedef int type; };
9356+
//
9357+
// template <typename V, typename... T>
9358+
// using alias = typename foo<sizeof...(T)>::type;
9359+
//
9360+
// template <typename... U>
9361+
// struct caller {
9362+
// typedef alias<int, int, U...> type;
9363+
// };
9364+
//
9365+
// template<typename caller<int>::type = 0>
9366+
// void function() {
9367+
// }
9368+
//
9369+
// int main() {
9370+
// function<0>();
9371+
// }
9372+
public void testSizeofParameterPack_574196_4() throws Exception {
9373+
parseAndCheckBindings();
9374+
}
9375+
9376+
// template <int> struct foo;
9377+
// template <> struct foo<2> { typedef int type; };
9378+
//
9379+
// template <typename V, int... T>
9380+
// using myalias = typename foo<sizeof...(T)>::type;
9381+
//
9382+
// template <int... U>
9383+
// struct caller {
9384+
// typedef myalias<int, 0, U...> type;
9385+
// };
9386+
//
9387+
// template<typename caller<0>::type = 4321>
9388+
// void function() {
9389+
// }
9390+
//
9391+
// int main() {
9392+
// function<1234>();
9393+
// }
9394+
//TODO: Handle non-type parameter pack
9395+
// public void testSizeofParameterPack_574196_5() throws Exception {
9396+
// parseAndCheckBindings();
9397+
// }
9398+
9399+
// template <int> struct foo;
9400+
// template <> struct foo<0> { typedef int type; };
9401+
//
9402+
// template <typename V, typename... T>
9403+
// using myalias = typename foo<sizeof...(T)>::type;
9404+
//
9405+
// template <typename... U>
9406+
// struct caller {
9407+
// typedef myalias<int, U...> type;
9408+
// };
9409+
//
9410+
// template<typename caller<>::type = 4321>
9411+
// void function() {
9412+
// }
9413+
//
9414+
// int main() {
9415+
// function<1234>();
9416+
// }
9417+
public void testSizeofParameterPack_574196_6() throws Exception {
9418+
parseAndCheckBindings();
9419+
}
9420+
92889421
// template <int, class>
92899422
// struct A {};
92909423
//

core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnary.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,11 @@ public static ICPPEvaluation unmarshal(short firstBytes, ITypeMarshalBuffer buff
399399

400400
@Override
401401
public ICPPEvaluation instantiate(InstantiationContext context, int maxDepth) {
402+
// if (fOperator == IASTUnaryExpression.op_sizeofParameterPack) {
403+
// //TODO: Something like EvalUnaryTypeID ?
404+
// return instantiateSizeofParameterPack(context);
405+
// }
406+
402407
if (fOperator == op_integerPack && context.getPackOffset() != -1) {
403408
return new EvalFixed(getType(), ValueCategory.PRVALUE, IntegralValue.create(context.getPackOffset()));
404409
}

core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalUnaryTypeID.java

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,13 @@
4444
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_typeid;
4545
import static org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression.op_typeof;
4646

47+
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
4748
import org.eclipse.cdt.core.dom.ast.IASTExpression.ValueCategory;
4849
import org.eclipse.cdt.core.dom.ast.IASTNode;
4950
import org.eclipse.cdt.core.dom.ast.IBinding;
5051
import org.eclipse.cdt.core.dom.ast.IType;
5152
import org.eclipse.cdt.core.dom.ast.IValue;
53+
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType;
5254
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
5355
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
5456
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
@@ -271,15 +273,15 @@ private ICPPEvaluation instantiateSizeofParameterPack(InstantiationContext conte
271273
return this;
272274
}
273275
int concreteArgCount = 0;
274-
boolean havePackExpansion = false;
276+
int packExpansionCount = 0;
275277
for (ICPPTemplateArgument arg : args) {
276278
if (arg.isPackExpansion()) {
277-
havePackExpansion = true;
279+
packExpansionCount++;
278280
} else {
279281
concreteArgCount++;
280282
}
281283
}
282-
if (havePackExpansion) {
284+
if (packExpansionCount > 0) {
283285
// TODO(bug 530103):
284286
// This will only handle correctly the case where there is a single argument
285287
// which is a pack expansion, and no concrete arguments.
@@ -291,7 +293,33 @@ private ICPPEvaluation instantiateSizeofParameterPack(InstantiationContext conte
291293
// sizeof...(P).
292294
// - Construct an EvalBinary tree representing the sum of |concreteArgCount|
293295
// and the EvalUnaryTypeIds from the previous step.
294-
return instantiateBySubstitution(context);
296+
297+
//malaperle: I implemented something that kind-of does what the comment
298+
//above suggest but am not confident enough that it covers all cases (hence the several instanceof checks).
299+
ICPPEvaluation packEval = null;
300+
for (ICPPTemplateArgument arg : args) {
301+
if (arg.isPackExpansion()) {
302+
if (arg.getTypeValue() instanceof ICPPParameterPackType) {
303+
ICPPParameterPackType parameterPackType = (ICPPParameterPackType) arg.getTypeValue();
304+
IType type = parameterPackType.getType();
305+
if (type instanceof ICPPTemplateParameter)
306+
packEval = new EvalUnaryTypeID(fOperator, type, getTemplateDefinition());
307+
308+
}
309+
}
310+
}
311+
312+
// Can we really get here?
313+
if (packEval == null)
314+
return instantiateBySubstitution(context);
315+
316+
// For sizeof(...(T)), T={U..., U...}
317+
ICPPEvaluation multiPackCountEval = new EvalBinary(IASTBinaryExpression.op_multiply, packEval,
318+
new EvalFixed(getType(), getValueCategory(), IntegralValue.create(packExpansionCount)),
319+
pack);
320+
321+
return new EvalBinary(IASTBinaryExpression.op_plus, multiPackCountEval,
322+
new EvalFixed(getType(), getValueCategory(), IntegralValue.create(concreteArgCount)), pack);
295323
} else {
296324
return new EvalFixed(getType(), getValueCategory(), IntegralValue.create(concreteArgCount));
297325
}

0 commit comments

Comments
 (0)