1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-24 17:35:35 +02:00

Bug 517670 - Handle instantiation of closure types

Change-Id: I82208dbb2ec0e11760cbd78a073acefa627d8d36
This commit is contained in:
Nathan Ridge 2017-06-02 03:00:26 -04:00
parent 27b9230cad
commit 0a639043fa
4 changed files with 128 additions and 8 deletions

View file

@ -11,7 +11,6 @@
*******************************************************************************/
package org.eclipse.cdt.core.parser.tests.ast2.cxx14;
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.ICPPField;
@ -23,13 +22,13 @@ 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.parser.ParserLanguage;
import org.eclipse.cdt.core.parser.tests.ast2.AST2TestBase;
import org.eclipse.cdt.core.parser.tests.ast2.AST2CPPTestBase;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassInstance;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFieldTemplateSpecialization;
import junit.framework.TestSuite;
public class VariableTemplateTests extends AST2TestBase {
public class VariableTemplateTests extends AST2CPPTestBase {
public static TestSuite suite() {
return suite(VariableTemplateTests.class);
@ -362,8 +361,13 @@ public class VariableTemplateTests extends AST2TestBase {
ICPPVariable waldo2 = ah.assertNonProblem("waldo2");
assertVariableValue(waldo2, 0);
}
private IASTTranslationUnit parseAndCheckBindings() throws Exception {
return parseAndCheckBindings(getAboveComment(), ParserLanguage.CPP);
// template <typename R>
// auto L = []{ return R{}; };
//
// decltype(L<int>()) waldo;
public void testLambdaValue_517670() throws Exception {
BindingAssertionHelper helper = getAssertionHelper();
helper.assertVariableType("waldo", CommonCPPTypes.int_);
}
}

View file

@ -0,0 +1,105 @@
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLambdaExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPTemplateParameterMap;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPUsingDeclaration;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
/**
* Specialization of a closure type.
*/
public class CPPClosureSpecialization extends CPPClosureType implements ICPPClassSpecialization {
private CPPClosureType fSpecialized;
private ICPPTemplateParameterMap fMap;
public CPPClosureSpecialization(ICPPASTLambdaExpression lambda, CPPClosureType specialized,
InstantiationContext context) {
super(lambda);
fSpecialized = specialized;
fMap = context.getParameterMap();
ICPPMethod[] methods = specialized.getMethods();
fMethods = new ICPPMethod[methods.length];
for (int i = 0; i < methods.length; ++i) {
fMethods[i] = (ICPPMethod) specializeMember(methods[i]);
}
}
@Override
public ICPPTemplateParameterMap getTemplateParameterMap() {
return fMap;
}
@Override
public ICPPClassType getSpecializedBinding() {
return fSpecialized;
}
@Override
public IBinding specializeMember(IBinding binding) {
// TODO: Cache specialized members the way class template specializations do?
return CPPTemplates.createSpecialization(this, binding);
}
@Override
public IBinding specializeMember(IBinding binding, IASTNode point) {
return specializeMember(binding);
}
@Override
public ICPPBase[] getBases(IASTNode point) {
return ICPPBase.EMPTY_BASE_ARRAY;
}
@Override
public ICPPConstructor[] getConstructors(IASTNode point) {
return getConstructors();
}
@Override
public ICPPField[] getDeclaredFields(IASTNode point) {
return ICPPField.EMPTY_CPPFIELD_ARRAY;
}
@Override
public ICPPMethod[] getMethods(IASTNode point) {
return getMethods();
}
@Override
public ICPPMethod[] getAllDeclaredMethods(IASTNode point) {
return ICPPMethod.EMPTY_CPPMETHOD_ARRAY;
}
@Override
public ICPPMethod[] getDeclaredMethods(IASTNode point) {
return ICPPMethod.EMPTY_CPPMETHOD_ARRAY;
}
@Override
public IBinding[] getFriends(IASTNode point) {
return IBinding.EMPTY_BINDING_ARRAY;
}
@Override
public ICPPField[] getFields(IASTNode point) {
return ICPPField.EMPTY_CPPFIELD_ARRAY;
}
@Override
public ICPPClassType[] getNestedClasses(IASTNode point) {
return ICPPClassType.EMPTY_CLASS_ARRAY;
}
@Override
public ICPPUsingDeclaration[] getUsingDeclarations(IASTNode point) {
return ICPPUsingDeclaration.EMPTY_USING_DECL_ARRAY;
}
}

View file

@ -69,7 +69,7 @@ public class CPPClosureType extends PlatformObject implements ICPPClassType, ICP
private final ICPPASTLambdaExpression fLambdaExpression;
private IType[] fParameterTypes;
private ICPPParameter[] fParameters;
private ICPPMethod[] fMethods;
protected ICPPMethod[] fMethods;
private ClassScope fScope;
// Used for generic lambdas; null otherwise.
private ICPPTemplateParameter[] fInventedTemplateParameters;
@ -77,7 +77,7 @@ public class CPPClosureType extends PlatformObject implements ICPPClassType, ICP
public CPPClosureType(ICPPASTLambdaExpression lambdaExpr) {
fLambdaExpression= lambdaExpr;
}
private ICPPMethod[] createMethods() {
boolean needConversionOperator=
fLambdaExpression.getCaptureDefault() == CaptureDefault.UNSPECIFIED &&
@ -451,6 +451,12 @@ public class CPPClosureType extends PlatformObject implements ICPPClassType, ICP
throw new IllegalArgumentException(member.getName() + " is not a member of closure type '" //$NON-NLS-1$
+ fLambdaExpression.getRawSignature() + "'"); //$NON-NLS-1$
}
// A lambda expression can appear in a dependent context, such as in the value of
// a variable template, so it needs to be instantiable.
public CPPClosureType instantiate(InstantiationContext context) {
return new CPPClosureSpecialization(fLambdaExpression, this, context);
}
private final class ClassScope implements ICPPClassScope {
@Override

View file

@ -143,6 +143,7 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassSpecialization.Recur
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassTemplatePartialSpecialization;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassTemplatePartialSpecializationSpecialization;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassTemplateSpecialization;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClosureType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPConstructorInstance;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPConstructorSpecialization;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPConstructorTemplateSpecialization;
@ -1663,6 +1664,10 @@ public class CPPTemplates {
default: return null; // shouldn't happen
}
}
if (type instanceof CPPClosureType) {
return ((CPPClosureType) type).instantiate(context);
}
return type;
} catch (DOMException e) {