From 1e598214eae17ec81453b572afb9b29fa1e62065 Mon Sep 17 00:00:00 2001 From: Nathan Ridge Date: Tue, 29 Dec 2015 22:04:46 -0500 Subject: [PATCH] Bug 484959 - Instantiate return expression of constexpr function template Change-Id: I3abec0f3bac58db77aacd61bd985c94c2185e3a8 Signed-off-by: Nathan Ridge --- .../parser/tests/ast2/AST2TemplateTests.java | 18 ++++++++++++++++++ .../core/parser/tests/ast2/AST2TestBase.java | 4 +--- .../tests/IndexCPPTemplateResolutionTest.java | 19 +++++++++++++++++++ .../core/testplugin/util/BaseTestCase.java | 7 +++++++ .../parser/cpp/CPPFunctionSpecialization.java | 15 ++++++++++++++- .../cpp/CPPTemplateNonTypeArgument.java | 3 --- .../dom/parser/cpp/semantics/EvalFixed.java | 10 +++++++++- 7 files changed, 68 insertions(+), 8 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 b1f5f80b0a0..f926b67c0a4 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 @@ -8752,6 +8752,24 @@ public class AST2TemplateTests extends AST2TestBase { public void testConstexprFunctionCallWithNonConstexprArguments_429891() throws Exception { parseAndCheckBindings(); } + + // template + // struct S; + // + // template <> + // struct S { + // static const int value = 42; + // }; + // + // template + // constexpr int foo() { + // return S::value; + // } + // + // constexpr int waldo = foo(); + public void testInstantiationOfReturnExpression_484959() throws Exception { + getAssertionHelper().assertVariableValue("waldo", 42); + } // template class A {}; // template class B {}; diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TestBase.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TestBase.java index 67f4a04eb31..538ca6f1de8 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TestBase.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2TestBase.java @@ -776,9 +776,7 @@ public class AST2TestBase extends BaseTestCase { public void assertVariableValue(String variableName, long expectedValue) { IVariable var = assertNonProblem(variableName); - assertNotNull(var.getInitialValue()); - assertNotNull(var.getInitialValue().numericalValue()); - assertEquals(expectedValue, var.getInitialValue().numericalValue().longValue()); + BaseTestCase.assertVariableValue(var, expectedValue); } public U assertType(T obj, Class... cs) { diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java index 88c8ce41e94..7c4153cc69c 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexCPPTemplateResolutionTest.java @@ -2644,6 +2644,25 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa public void testSpecializationOfConstexprFunction_420995() throws Exception { checkBindings(); } + + // template + // struct S; + // + // template <> + // struct S { + // static const int value = 42; + // }; + // + // template + // constexpr int foo() { + // return S::value; + // } + + // constexpr int waldo = foo(); + public void testInstantiationOfReturnExpression_484959() throws Exception { + ICPPVariable waldo = getBindingFromASTName("waldo", 5); + assertVariableValue(waldo, 42); + } // template // class waldo { diff --git a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase.java b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase.java index 606fb5ab88c..67dbfb78fe0 100644 --- a/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase.java +++ b/core/org.eclipse.cdt.core.tests/suite/org/eclipse/cdt/core/testplugin/util/BaseTestCase.java @@ -32,6 +32,7 @@ import junit.framework.TestResult; import junit.framework.TestSuite; import org.eclipse.cdt.core.CCorePlugin; +import org.eclipse.cdt.core.dom.ast.IVariable; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.ElementChangedEvent; @@ -349,4 +350,10 @@ public class BaseTestCase extends TestCase { } return clazz.cast(o); } + + protected static void assertVariableValue(IVariable var, long expectedValue) { + assertNotNull(var.getInitialValue()); + assertNotNull(var.getInitialValue().numericalValue()); + assertEquals(expectedValue, var.getInitialValue().numericalValue().longValue()); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionSpecialization.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionSpecialization.java index 72e6cfadb14..747df032bac 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionSpecialization.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPFunctionSpecialization.java @@ -35,6 +35,8 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap; import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.internal.core.dom.parser.ASTInternal; import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; +import org.eclipse.cdt.internal.core.dom.parser.Value; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; /** @@ -330,7 +332,18 @@ public class CPPFunctionSpecialization extends CPPSpecialization implements ICPP } IBinding f = getSpecializedBinding(); if (f instanceof ICPPComputableFunction) { - return ((ICPPComputableFunction) f).getReturnExpression(); + ICPPEvaluation eval = ((ICPPComputableFunction) f).getReturnExpression(); + if (eval != null) { + // TODO: Should we instead do this when the CPPFunctionSpecialization is created? + // It would mean getting a more accurate point of instantiation, but it would also + // mean doing the instantiation when we might never need it. + IASTNode point = f instanceof ICPPInternalFunction + ? ((ICPPInternalFunction) f).getDefinition() + : null; + eval = eval.instantiate(getTemplateParameterMap(), -1, + CPPTemplates.getSpecializationContext(getOwner()), Value.MAX_RECURSION_DEPTH, point); + } + return eval; } return null; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateNonTypeArgument.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateNonTypeArgument.java index 4059477b1e9..41c52a2d28b 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateNonTypeArgument.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPTemplateNonTypeArgument.java @@ -39,9 +39,6 @@ public class CPPTemplateNonTypeArgument implements ICPPTemplateArgument { IValue value = evaluation.getValue(point); if (value == Value.ERROR) { fEvaluation = EvalFixed.INCOMPLETE; - } else if (value.getEvaluation() instanceof EvalFixed) { - // Avoid nesting EvalFixed's as nesting causes the signature to be different. - fEvaluation = value.getEvaluation(); } else { fEvaluation= new EvalFixed(evaluation.getType(point), evaluation.getValueCategory(point), value); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFixed.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFixed.java index b2a230fec75..f4bdccf2b27 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFixed.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/EvalFixed.java @@ -45,6 +45,14 @@ public class EvalFixed extends CPPEvaluation { private boolean fCheckedIsValueDependent; public EvalFixed(IType type, ValueCategory cat, IValue value) { + // Avoid nesting EvalFixed's as nesting causes the signature to be different. + if (value.getEvaluation() instanceof EvalFixed) { + EvalFixed inner = (EvalFixed) value.getEvaluation(); + type = inner.fType; + cat = inner.fValueCategory; + value = inner.fValue; + } + if (type instanceof CPPBasicType) { Long num = value.numericalValue(); if (num != null) { @@ -57,7 +65,7 @@ public class EvalFixed extends CPPEvaluation { fValueCategory= cat; fValue= value; } - + public IType getType() { return fType; }