1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-08 10:16:03 +02:00

Bug 494216 - Instantiation of variable templates with dependent arguments

Change-Id: If9c27267d25ce8cccb89e7a5404bf5e3e6480dcb
This commit is contained in:
Nathan Ridge 2016-06-13 12:21:23 -04:00
parent e6ed5e4037
commit c180a3e798
3 changed files with 70 additions and 5 deletions

View file

@ -12,14 +12,18 @@
package org.eclipse.cdt.core.parser.tests.ast2; package org.eclipse.cdt.core.parser.tests.ast2;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisibilityLabel; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisibilityLabel;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField; import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFieldTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPFieldTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPPartialSpecialization; import org.eclipse.cdt.core.dom.ast.cpp.ICPPPartialSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateArgument;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition; import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariableInstance; import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariableInstance;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariableTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariableTemplate;
import org.eclipse.cdt.core.parser.ParserLanguage; import org.eclipse.cdt.core.parser.ParserLanguage;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassInstance;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFieldTemplateSpecialization; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFieldTemplateSpecialization;
import junit.framework.TestSuite; import junit.framework.TestSuite;
@ -309,6 +313,34 @@ public class AST2VariableTemplateTests extends AST2TestBase {
assertEquals(template, bInst.getSpecializedBinding()); assertEquals(template, bInst.getSpecializedBinding());
} }
// template <typename T>
// struct meta {
// static const bool value = true;
// };
//
// template <typename T>
// constexpr bool var = meta<T>::value;
//
// template <bool> struct S {};
//
// template <typename T>
// S<var<T>> foo();
//
// void bar() {
// auto waldo = foo<int>();
// }
public void test_bug494216() throws Exception {
parseAndCheckBindings();
BindingAssertionHelper ah = getAssertionHelper(ParserLanguage.CPP);
ICPPVariable waldo = ah.assertNonProblem("waldo");
IType type = waldo.getType();
assertInstance(type, CPPClassInstance.class);
ICPPTemplateArgument[] args = ((CPPClassInstance) type).getTemplateArguments();
assertEquals(1, args.length);
assertValue(args[0].getNonTypeValue(), 1);
}
private IASTTranslationUnit parseAndCheckBindings() throws Exception { private IASTTranslationUnit parseAndCheckBindings() throws Exception {
return parseAndCheckBindings(getAboveComment(), ParserLanguage.CPP); return parseAndCheckBindings(getAboveComment(), ParserLanguage.CPP);
} }

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.IValue;
import org.eclipse.cdt.core.dom.ast.IVariable; 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;
@ -358,9 +359,13 @@ public class BaseTestCase extends TestCase {
return clazz.cast(o); return clazz.cast(o);
} }
protected static void assertValue(IValue value, long expectedValue) {
assertNotNull(value);
assertNotNull(value.numericalValue());
assertEquals(expectedValue, value.numericalValue().longValue());
}
protected static void assertVariableValue(IVariable var, long expectedValue) { protected static void assertVariableValue(IVariable var, long expectedValue) {
assertNotNull(var.getInitialValue()); assertValue(var.getInitialValue(), expectedValue);
assertNotNull(var.getInitialValue().numberValue());
assertEquals(expectedValue, var.getInitialValue().numberValue().longValue());
} }
} }

View file

@ -112,6 +112,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPTypeSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUnaryTypeTransformation; import org.eclipse.cdt.core.dom.ast.cpp.ICPPUnaryTypeTransformation;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable; import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariable;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariableInstance;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariableTemplate; import org.eclipse.cdt.core.dom.ast.cpp.ICPPVariableTemplate;
import org.eclipse.cdt.core.index.IIndexBinding; import org.eclipse.cdt.core.index.IIndexBinding;
import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.core.parser.util.ArrayUtil;
@ -254,7 +255,7 @@ public class CPPTemplates {
return createProblem(template, IProblemBinding.SEMANTIC_INVALID_TEMPLATE_ARGUMENTS, point); return createProblem(template, IProblemBinding.SEMANTIC_INVALID_TEMPLATE_ARGUMENTS, point);
if (template instanceof ICPPTemplateTemplateParameter || hasDependentArgument(arguments)) { if (template instanceof ICPPTemplateTemplateParameter || hasDependentArgument(arguments)) {
return deferredInstance(template, arguments); return deferredInstance(template, arguments, point);
} }
if (template instanceof ICPPClassTemplatePartialSpecialization) { if (template instanceof ICPPClassTemplatePartialSpecialization) {
@ -500,7 +501,8 @@ public class CPPTemplates {
} }
} }
private static IBinding deferredInstance(ICPPPartiallySpecializable template, ICPPTemplateArgument[] arguments) throws DOMException { private static IBinding deferredInstance(ICPPPartiallySpecializable template,
ICPPTemplateArgument[] arguments, IASTNode point) throws DOMException {
ICPPTemplateInstance instance= getInstance(template, arguments, false); ICPPTemplateInstance instance= getInstance(template, arguments, false);
if (instance != null) if (instance != null)
return instance; return instance;
@ -509,6 +511,16 @@ public class CPPTemplates {
instance = new CPPDeferredClassInstance((ICPPClassTemplate) template, arguments); instance = new CPPDeferredClassInstance((ICPPClassTemplate) template, arguments);
addInstance(template, arguments, instance); addInstance(template, arguments, instance);
} }
if (template instanceof ICPPVariableTemplate) {
// TODO(nathanridge): Do we need a CPPDeferredVariableInstance?
ICPPVariableTemplate variableTemplate = ((ICPPVariableTemplate) template);
CPPTemplateParameterMap tpMap = createParameterMap(template, arguments, point);
InstantiationContext context = new InstantiationContext(tpMap, point);
IType type = instantiateType(variableTemplate.getType(), context);
IValue value = instantiateValue(variableTemplate.getInitialValue(), context,
Value.MAX_RECURSION_DEPTH);
instance = new CPPVariableInstance(template, template.getOwner(), tpMap, arguments, type, value);
}
return instance; return instance;
} }
@ -1712,6 +1724,22 @@ public class CPPTemplates {
result.setParameters(specializeParameters(origInstance.getParameters(), result, context, maxDepth)); result.setParameters(specializeParameters(origInstance.getParameters(), result, context, maxDepth));
return result; return result;
} }
} else if (binding instanceof ICPPVariableInstance) {
// TODO(nathanridge):
// Similar to the ICPPFunctionInstance case above, perhaps we should have an
// ICPPDeferredVariableInstance.
ICPPVariableInstance origInstance = (ICPPVariableInstance) binding;
ICPPTemplateArgument[] origArgs = origInstance.getTemplateArguments();
ICPPTemplateArgument[] newArgs = instantiateArguments(origArgs, context, false);
if (origArgs != newArgs) {
CPPTemplateParameterMap newMap = instantiateArgumentMap(
origInstance.getTemplateParameterMap(), context);
IType newType = instantiateType(origInstance.getType(), context);
IValue newValue = instantiateValue(origInstance.getInitialValue(), context,
Value.MAX_RECURSION_DEPTH);
return new CPPVariableInstance(origInstance.getTemplateDefinition(), origInstance.getOwner(),
newMap, newArgs, newType, newValue);
}
} }
return binding; return binding;
} }