1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-08 18:26:01 +02:00

Bug 401743 - NullPointerException in EvalBinding.instantiate() - tpMap

is null

Change-Id: Iea69ddf7f1872f0e1b0a918faed400b6d5d4f2f7
Reviewed-on: https://git.eclipse.org/r/10641
Reviewed-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
IP-Clean: Sergey Prigogin <eclipse.sprigogin@gmail.com>
Tested-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
This commit is contained in:
Nathan Ridge 2013-02-25 16:21:49 -05:00 committed by Sergey Prigogin
parent 9c4d88dab4
commit 773aa77a2a
4 changed files with 48 additions and 6 deletions

View file

@ -7334,4 +7334,29 @@ public class AST2TemplateTests extends AST2TestBase {
public void testVariadicNonTypeTemplateParameter_401400() throws Exception {
parseAndCheckBindings();
}
// template <int...> struct tuple_indices {};
// template <int Sp, class IntTuple, int Ep>
// struct make_indices_imp;
// template <int Sp, int ...Indices, int Ep>
// struct make_indices_imp<Sp, tuple_indices<Indices...>, Ep> {
// typedef typename make_indices_imp<Sp + 1, tuple_indices<Indices..., Sp>, Ep>::type type;
// };
// template <int Ep, int ...Indices>
// struct make_indices_imp<Ep, tuple_indices<Indices...>, Ep> {
// typedef tuple_indices<Indices...> type;
// };
// template <int Ep, int Sp = 0>
// struct make_tuple_indices {
// typedef typename make_indices_imp<Sp, tuple_indices<>, Ep>::type type;
// };
// template <class ... Args>
// class async_func {
// void operator()() {
// typedef typename make_tuple_indices<1 + sizeof...(Args), 1>::type Index;
// }
// };
public void testVariadicTemplatesNPE_401743() throws Exception {
parseAndCheckBindings();
}
}

View file

@ -402,6 +402,18 @@ public class Value implements IValue {
public static boolean isDependentValue(IValue nonTypeValue) {
if (nonTypeValue == null)
return false;
// Unknown values may or may not be dependent. In the case of a template with
// a non-type template argument, whether or not the argument's value is dependent
// determines whether or not the template gets instantiated. In light of this,
// it's safer to assume that an unknown value is dependent because:
// 1. Instantiating a template with a non-type template argument whose value is
// unknown is useless.
// 2. Instantiating such a template can lead to an infinite recursion of
// instantiations (e.g. consider a template A<N> that delegates to A<N - 1>,
// with A<0> being specialized to end the recursion - if N is unknown,
// N - 1 will be unknown as well, and we get an infinite recursion).
if (nonTypeValue == UNKNOWN)
return true;
ICPPEvaluation eval = nonTypeValue.getEvaluation();
return eval != null && eval.isValueDependent();
}

View file

@ -279,6 +279,11 @@ public class EvalBinding extends CPPDependentEvaluation {
value= ((IVariable) fBinding).getInitialValue();
} else if (fBinding instanceof IEnumerator) {
value= ((IEnumerator) fBinding).getValue();
} else if (fBinding instanceof IFunction) {
// If a function passed as a non-type template parameter is constexpr,
// it can be used inside the template as a constexpr function, so it's
// important to preserve the binding in the value.
value = Value.create(this);
}
if (value == null)
value = Value.UNKNOWN;
@ -336,10 +341,12 @@ public class EvalBinding extends CPPDependentEvaluation {
ICPPClassSpecialization within, int maxdepth, IASTNode point) {
IBinding origBinding = getBinding();
if (origBinding instanceof ICPPTemplateNonTypeParameter) {
if (tpMap != null) {
ICPPTemplateArgument argument = tpMap.getArgument((ICPPTemplateNonTypeParameter) origBinding, packOffset);
if (argument != null && argument.isNonTypeValue()) {
return argument.getNonTypeEvaluation();
}
}
// TODO(sprigogin): Do we need something similar for pack expansion?
} else if (origBinding instanceof ICPPParameter) {
ICPPParameter parameter = (ICPPParameter) origBinding;

View file

@ -354,10 +354,8 @@ public class EvalID extends CPPDependentEvaluation {
return new EvalFunctionSet(new CPPFunctionSet(functions, templateArgs, null), fAddressOf, getTemplateDefinition());
}
IBinding binding = bindings.length == 1 ? bindings[0] : null;
if (binding instanceof IEnumerator) {
if (binding instanceof IEnumerator || binding instanceof ICPPMember) {
return new EvalBinding(binding, null, getTemplateDefinition());
} else if (binding instanceof ICPPMember) {
return new EvalMemberAccess(nameOwner, ValueCategory.PRVALUE, binding, false, getTemplateDefinition());
} else if (binding instanceof CPPFunctionSet) {
return new EvalFunctionSet((CPPFunctionSet) binding, fAddressOf, getTemplateDefinition());
}