1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-08 01:25:23 +02:00

Bug 530086 - Instantiation of template argument where substituted argument is a pack expansion

The first patch for bug 527697 made us not instantiate such an
argument, because determinePackSize() would return PACK_SIZE_DEFER.

The motivation for that fix was to avoid sizeof...(T) prematurely
instantiating to a concrete value in cases where T was mapped to
a pack expansion.

This patch reverts the change to determinePackSize() and applies a
different fix for the sizeof...(T), specific to EvalUnaryTypeId.

Change-Id: Idc231aeecb5d50e93dda364c6d2deb08057cc8b6
This commit is contained in:
Nathan Ridge 2018-01-21 22:52:53 -05:00
parent 911376f775
commit 5c8a84960c
3 changed files with 67 additions and 20 deletions

View file

@ -10557,7 +10557,23 @@ public class AST2TemplateTests extends AST2CPPTestBase {
//
// template <int... I>
// void foo(index_sequence<I...>);
public void testTemplateAliasWithVariadicNonTypeArgs_530086() throws Exception {
public void testTemplateAliasWithVariadicNonTypeArgs_530086a() throws Exception {
parseAndCheckBindings();
}
// template <int...>
// struct integer_sequence {};
//
// template <int... I>
// using index_sequence = integer_sequence<I...>;
//
// template <typename, int... I>
// void bar(index_sequence<I...>);
//
// void foo() {
// bar<int>(integer_sequence<0>{});
// }
public void testTemplateAliasWithVariadicArgs_530086b() throws Exception {
parseAndCheckBindings();
}
}

View file

@ -222,7 +222,7 @@ public class CPPTemplates {
// Used to indicate that two different packs with different sizes were found.
static final int PACK_SIZE_FAIL = -2;
// Used to indicate that no template parameter packs were found.
static final int PACK_SIZE_NOT_FOUND = Integer.MAX_VALUE;
@ -1224,14 +1224,6 @@ public class CPPTemplates {
if (tpar.isParameterPack()) {
ICPPTemplateArgument[] args= tpMap.getPackExpansion(tpar);
if (args != null) {
// The arguments could be dependent, so they could themselves
// contain pack expansions.
for (ICPPTemplateArgument arg : args) {
if (arg.isPackExpansion()) {
return PACK_SIZE_DEFER;
}
}
return args.length;
}
return PACK_SIZE_DEFER;

View file

@ -43,6 +43,8 @@ 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.ICPPTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
import org.eclipse.cdt.internal.core.dom.parser.DependentValue;
import org.eclipse.cdt.internal.core.dom.parser.ITypeMarshalBuffer;
@ -208,17 +210,9 @@ public class EvalUnaryTypeID extends CPPDependentEvaluation {
@Override
public ICPPEvaluation instantiate(InstantiationContext context, int maxDepth) {
if (fOperator == op_sizeofParameterPack) {
int packSize = determinePackSize(context.getParameterMap());
if (packSize == CPPTemplates.PACK_SIZE_FAIL || packSize == CPPTemplates.PACK_SIZE_NOT_FOUND) {
return EvalFixed.INCOMPLETE;
} else if (packSize != CPPTemplates.PACK_SIZE_DEFER) {
return new EvalFixed(getType(), getValueCategory(), IntegralValue.create(packSize));
}
return instantiateSizeofParameterPack(context);
}
IType type = CPPTemplates.instantiateType(fOrigType, context);
if (type == fOrigType)
return this;
return new EvalUnaryTypeID(fOperator, type, getTemplateDefinition());
return instantiateBySubstitution(context);
}
@Override
@ -235,4 +229,49 @@ public class EvalUnaryTypeID extends CPPDependentEvaluation {
public boolean referencesTemplateParameter() {
return CPPTemplates.isDependentType(fOrigType);
}
private ICPPEvaluation instantiateBySubstitution(InstantiationContext context) {
IType type = CPPTemplates.instantiateType(fOrigType, context);
if (type == fOrigType)
return this;
return new EvalUnaryTypeID(fOperator, type, getTemplateDefinition());
}
private ICPPEvaluation instantiateSizeofParameterPack(InstantiationContext context) {
if (fOrigType instanceof ICPPTemplateParameter) {
ICPPTemplateParameter pack = (ICPPTemplateParameter) fOrigType;
if (pack.isParameterPack()) {
ICPPTemplateArgument[] args = context.getPackExpansion(pack);
if (args == null) {
return this;
}
int concreteArgCount = 0;
boolean havePackExpansion = false;
for (ICPPTemplateArgument arg : args) {
if (arg.isPackExpansion()) {
havePackExpansion = true;
} else {
concreteArgCount++;
}
}
if (havePackExpansion) {
// 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.
// To correctly handle cases with multiple pack expansions, or a mixture
// of concrete arguments and pack expansions, we need to do the following:
// - For each pack expansion, find the parameter pack P which it's
// expanding (if it's expanding multiple parameter packs, any one
// should be sufficient), and construct an EvalUnaryTypeId representing
// sizeof...(P).
// - Construct an EvalBinary tree representing the sum of |concreteArgCount|
// and the EvalUnaryTypeIds from the previous step.
return instantiateBySubstitution(context);
} else {
return new EvalFixed(getType(), getValueCategory(), IntegralValue.create(concreteArgCount));
}
}
}
return EvalFixed.INCOMPLETE;
}
}