Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TemplateTests.java25
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/Value.java12
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalBinding.java13
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalID.java4
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());
}

Back to the top