1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-15 13:05:22 +02:00

Bug 484959 - Instantiate return expression of constexpr function

template

Change-Id: I3abec0f3bac58db77aacd61bd985c94c2185e3a8
Signed-off-by: Nathan Ridge <zeratul976@hotmail.com>
This commit is contained in:
Nathan Ridge 2015-12-29 22:04:46 -05:00 committed by Sergey Prigogin
parent ad2940f594
commit 1e598214ea
7 changed files with 68 additions and 8 deletions

View file

@ -8753,6 +8753,24 @@ public class AST2TemplateTests extends AST2TestBase {
parseAndCheckBindings(); parseAndCheckBindings();
} }
// template <typename>
// struct S;
//
// template <>
// struct S<int> {
// static const int value = 42;
// };
//
// template <typename T>
// constexpr int foo() {
// return S<T>::value;
// }
//
// constexpr int waldo = foo<int>();
public void testInstantiationOfReturnExpression_484959() throws Exception {
getAssertionHelper().assertVariableValue("waldo", 42);
}
// template <typename> class A {}; // template <typename> class A {};
// template <int> class B {}; // template <int> class B {};
// const int D = 4; // const int D = 4;

View file

@ -776,9 +776,7 @@ public class AST2TestBase extends BaseTestCase {
public void assertVariableValue(String variableName, long expectedValue) { public void assertVariableValue(String variableName, long expectedValue) {
IVariable var = assertNonProblem(variableName); IVariable var = assertNonProblem(variableName);
assertNotNull(var.getInitialValue()); BaseTestCase.assertVariableValue(var, expectedValue);
assertNotNull(var.getInitialValue().numericalValue());
assertEquals(expectedValue, var.getInitialValue().numericalValue().longValue());
} }
public <T, U extends T> U assertType(T obj, Class... cs) { public <T, U extends T> U assertType(T obj, Class... cs) {

View file

@ -2645,6 +2645,25 @@ public class IndexCPPTemplateResolutionTest extends IndexBindingResolutionTestBa
checkBindings(); checkBindings();
} }
// template <typename>
// struct S;
//
// template <>
// struct S<int> {
// static const int value = 42;
// };
//
// template <typename T>
// constexpr int foo() {
// return S<T>::value;
// }
// constexpr int waldo = foo<int>();
public void testInstantiationOfReturnExpression_484959() throws Exception {
ICPPVariable waldo = getBindingFromASTName("waldo", 5);
assertVariableValue(waldo, 42);
}
// template <class TYPE> // template <class TYPE>
// class waldo { // class waldo {
// enum { // enum {

View file

@ -32,6 +32,7 @@ import junit.framework.TestResult;
import junit.framework.TestSuite; import junit.framework.TestSuite;
import org.eclipse.cdt.core.CCorePlugin; 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.index.IIndex;
import org.eclipse.cdt.core.model.CoreModel; import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.ElementChangedEvent; import org.eclipse.cdt.core.model.ElementChangedEvent;
@ -349,4 +350,10 @@ public class BaseTestCase extends TestCase {
} }
return clazz.cast(o); 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());
}
} }

View file

@ -35,6 +35,8 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal; 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.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; 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(); IBinding f = getSpecializedBinding();
if (f instanceof ICPPComputableFunction) { 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; return null;
} }

View file

@ -39,9 +39,6 @@ public class CPPTemplateNonTypeArgument implements ICPPTemplateArgument {
IValue value = evaluation.getValue(point); IValue value = evaluation.getValue(point);
if (value == Value.ERROR) { if (value == Value.ERROR) {
fEvaluation = EvalFixed.INCOMPLETE; 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 { } else {
fEvaluation= new EvalFixed(evaluation.getType(point), fEvaluation= new EvalFixed(evaluation.getType(point),
evaluation.getValueCategory(point), value); evaluation.getValueCategory(point), value);

View file

@ -45,6 +45,14 @@ public class EvalFixed extends CPPEvaluation {
private boolean fCheckedIsValueDependent; private boolean fCheckedIsValueDependent;
public EvalFixed(IType type, ValueCategory cat, IValue value) { 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) { if (type instanceof CPPBasicType) {
Long num = value.numericalValue(); Long num = value.numericalValue();
if (num != null) { if (num != null) {