mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-08 18:26:01 +02:00
Bug 494216 - Instantiation of variable templates with dependent arguments
Change-Id: If9c27267d25ce8cccb89e7a5404bf5e3e6480dcb
This commit is contained in:
parent
e6ed5e4037
commit
c180a3e798
3 changed files with 70 additions and 5 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue