1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 22:52:11 +02:00

Bug 479138 - Make template instantiation fail if a non-type argument has

Value.ERROR as its value

This avoids infinite recursion in metaprograms whose termination depends
on the inputs being known.

Change-Id: Ic6972188f69bf324431ce1331ad079fbf2c9039e
Signed-off-by: Nathan Ridge <zeratul976@hotmail.com>
This commit is contained in:
Nathan Ridge 2015-11-26 20:31:38 -05:00 committed by Sergey Prigogin
parent 28c22cca09
commit c531b2d5e6
2 changed files with 68 additions and 2 deletions

View file

@ -2784,4 +2784,67 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa
public void testRedeclarationWithUnnamedTemplateParameter_472199() throws Exception { public void testRedeclarationWithUnnamedTemplateParameter_472199() throws Exception {
checkBindings(); checkBindings();
} }
// template<long _Ax> struct _GcdX {
// static const long value = _GcdX<_Ax - 1>::value;
// };
//
// template<> struct _GcdX<0> {
// static const long value = 0;
// };
//
// template<long _Ax> struct R {
// // static const long value = _Ax;
// };
//
// template<class _R1> struct Operation {
// static const long _N1 = _R1::value;
// typedef R<_GcdX<_N1>::value> value;
// };
//
// typedef Operation< R<1> >::value MYTYPE;
// // empty file
public void testRecursiveTemplateInstantiation_479138a() throws Exception {
// This tests that a template metaprogram whose termination depends on
// its inputs being known, doesn't cause a stack overflow when its
// inputs are not known.
checkBindings();
}
// template<long _Ax, long _Bx> struct _GcdX {
// static const long value = _GcdX<_Bx, _Ax % _Bx>::value;
// };
//
// template<long _Ax> struct _GcdX<_Ax, 0> {
// static const long value = _Ax;
// };
//
// template<long _Ax, long _Bx> struct _Gcd {
// static const long value = _GcdX<_Ax, _Bx>::value;
// };
//
// template<> struct _Gcd<0, 0> {
// static const long value = 1;
// };
//
// template<long _Ax> struct R {
// // static const long value = _Ax;
// };
//
// template<class _R1> struct Operation {
// static const long _N1 = _R1::value;
// typedef R<_Gcd<_N1, _N1>::value> value;
// };
//
//
// typedef Operation< R<1> >::value MYTYPE;
// // empty file
public void testRecursiveTemplateInstantiation_479138b() throws Exception {
// This is similar to 479138a, but the metaprogram additionally has
// exponential memory usage when the inputs are unknown and thus
// intermediate results cannot be collapsed into a single value.
checkBindings();
}
} }

View file

@ -18,6 +18,7 @@ import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.IValue; 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.ICPPParameterPackType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.internal.core.dom.parser.Value;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalFixed;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalParameterPack; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalParameterPack;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalTypeId; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.EvalTypeId;
@ -36,8 +37,10 @@ public class CPPTemplateNonTypeArgument implements ICPPTemplateArgument {
fEvaluation= evaluation; fEvaluation= evaluation;
} else { } else {
IValue value = evaluation.getValue(point); IValue value = evaluation.getValue(point);
// Avoid nesting EvalFixed's as nesting causes the signature to be different. if (value == Value.ERROR) {
if (value.getEvaluation() instanceof EvalFixed) { fEvaluation = EvalFixed.INCOMPLETE;
} else if (value.getEvaluation() instanceof EvalFixed) {
// Avoid nesting EvalFixed's as nesting causes the signature to be different.
fEvaluation = value.getEvaluation(); fEvaluation = value.getEvaluation();
} else { } else {
fEvaluation= new EvalFixed(evaluation.getTypeOrFunctionSet(point), fEvaluation= new EvalFixed(evaluation.getTypeOrFunctionSet(point),