diff options
4 files changed, 48 insertions, 6 deletions
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java index 10fb36e671f..54feea4966d 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java @@ -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(); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/Value.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/Value.java index dbb79403e81..21bf02ae84e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/Value.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/Value.java @@ -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(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java index a59760b7055..1f5101a1df2 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java @@ -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,9 +341,11 @@ public class EvalBinding extends CPPDependentEvaluation { ICPPClassSpecialization within, int maxdepth, IASTNode point) { IBinding origBinding = getBinding(); if (origBinding instanceof ICPPTemplateNonTypeParameter) { - ICPPTemplateArgument argument = tpMap.getArgument((ICPPTemplateNonTypeParameter) origBinding, packOffset); - if (argument != null && argument.isNonTypeValue()) { - return argument.getNonTypeEvaluation(); + 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) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java index 49960745ddc..1b50bb7f038 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java @@ -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()); } |