1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-22 14:12:10 +02:00

Bug 528457 - Store lambda parameters in index

The special binding type CPPLambdaExpressionParameter is removed.
Instead, a lambda expression parameters's are represented as
regular CPPParameters owned by the closure type's generated
function call operator.

Change-Id: I4afeac90c2595a1f84dfa59f057d0494b64d079c
This commit is contained in:
Nathan Ridge 2017-05-18 01:10:45 -04:00
parent ce18aad766
commit a8ff78b531
7 changed files with 76 additions and 205 deletions

View file

@ -72,8 +72,7 @@ public class GenericLambdaIndexTests extends IndexBindingResolutionTestBase {
// waldo(foo(L(42, 'x')));
// waldo(bar(L(42, 'x', 42.0f)));
// }
public void _testVariadicAutoParameter() throws Exception {
// TODO: To pass this test, we need to store lambda parameters in the index.
public void testVariadicAutoParameter() throws Exception {
checkBindings();
}

View file

@ -109,6 +109,17 @@ public class CPPASTConversionName extends CPPASTNameBase implements ICPPASTConve
return fName;
}
public static char[] createName(String targetName) {
StringBuilder buf = new StringBuilder();
buf.append(Keywords.cOPERATOR);
buf.append(' ');
buf.append(targetName);
final int len= buf.length();
char[] name= new char[len];
buf.getChars(0, len, name, 0);
return name;
}
public static char[] createName(IType t, IASTNode typeId) {
StringBuilder buf= new StringBuilder();
buf.append(Keywords.cOPERATOR);

View file

@ -67,6 +67,8 @@ import org.eclipse.core.runtime.PlatformObject;
*/
public class CPPClosureType extends PlatformObject implements ICPPClassType, ICPPInternalBinding {
private final ICPPASTLambdaExpression fLambdaExpression;
private IType[] fParameterTypes;
private ICPPParameter[] fParameters;
private ICPPMethod[] fMethods;
private ClassScope fScope;
// Used for generic lambdas; null otherwise.
@ -113,10 +115,7 @@ public class CPPClosureType extends PlatformObject implements ICPPClassType, ICP
final IType[] parameterTypes= getParameterTypes();
ft= new CPPFunctionType(returnType, parameterTypes, !isMutable(), false, false, false, false);
ICPPParameter[] params = new ICPPParameter[parameterTypes.length];
for (int i = 0; i < params.length; i++) {
params[i]= new CPPParameter(parameterTypes[i], i);
}
ICPPParameter[] params = getParameters();
char[] operatorParensName = OverloadableOperator.PAREN.toCharArray();
if (isGeneric()) {
m = new CPPImplicitMethodTemplate(getInventedTemplateParameterList(), scope, operatorParensName,
@ -136,7 +135,10 @@ public class CPPClosureType extends PlatformObject implements ICPPClassType, ICP
if (needConversionOperator) {
final CPPFunctionType conversionTarget = new CPPFunctionType(returnType, parameterTypes);
ft= new CPPFunctionType(conversionTarget, IType.EMPTY_TYPE_ARRAY, true, false, false, false, false);
char[] conversionOperatorName = CPPASTConversionName.createName(conversionTarget, null);
// Calling CPPASTConversionName.createName(IType) would try to stringize the type to
// construct a name, which is unnecessary work (not to mention prone to recursion with
// dependent types). Since the name doesn't matter anyways, just make one up.
char[] conversionOperatorName = CPPASTConversionName.createName("__fptr"); //$NON-NLS-1$
if (isGeneric()) {
ICPPTemplateParameter[] templateParams = getInventedTemplateParameterList();
// Clone the template parameters, since they are used by the function call operator,
@ -236,11 +238,32 @@ public class CPPClosureType extends PlatformObject implements ICPPClassType, ICP
}
private IType[] getParameterTypes() {
ICPPASTFunctionDeclarator lambdaDtor = fLambdaExpression.getDeclarator();
if (lambdaDtor != null) {
return CPPVisitor.createParameterTypes(lambdaDtor);
if (fParameterTypes == null) {
ICPPASTFunctionDeclarator lambdaDtor = fLambdaExpression.getDeclarator();
if (lambdaDtor != null) {
fParameterTypes = CPPVisitor.createParameterTypes(lambdaDtor);
} else {
fParameterTypes = IType.EMPTY_TYPE_ARRAY;
}
}
return IType.EMPTY_TYPE_ARRAY;
return fParameterTypes;
}
public ICPPParameter[] getParameters() {
if (fParameters == null) {
final IType[] parameterTypes= getParameterTypes();
fParameters = new ICPPParameter[parameterTypes.length];
ICPPASTFunctionDeclarator lambdaDtor = fLambdaExpression.getDeclarator();
if (lambdaDtor != null) {
ICPPASTParameterDeclaration[] paramDecls = lambdaDtor.getParameters();
for (int i = 0; i < fParameters.length; i++) {
CPPParameter param = new CPPParameter(parameterTypes[i], i);
param.addDeclaration(paramDecls[i].getDeclarator().getName());
fParameters[i] = param;
}
}
}
return fParameters;
}
@Override

View file

@ -1,180 +0,0 @@
/*******************************************************************************
* Copyright (c) 2010, 2014 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Markus Schorn (Wind River Systems) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ILinkage;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.IValue;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLambdaExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType;
import org.eclipse.cdt.internal.core.dom.Linkage;
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
import org.eclipse.core.runtime.PlatformObject;
/**
* Binding for a c++ function parameter
*/
public class CPPLambdaExpressionParameter extends PlatformObject implements ICPPParameter {
private IType fType;
private IASTName fDeclaration;
public CPPLambdaExpressionParameter(IASTName name) {
fDeclaration = name;
}
@Override
public boolean isParameterPack() {
return getType() instanceof ICPPParameterPackType;
}
@Override
public String getName() {
return new String(getNameCharArray());
}
@Override
public char[] getNameCharArray() {
return fDeclaration.getSimpleID();
}
@Override
public IScope getScope() {
return CPPVisitor.getContainingScope(fDeclaration);
}
@Override
public IType getType() {
if (fType == null) {
IASTNode parent= fDeclaration.getParent();
while (parent != null) {
if (parent instanceof ICPPASTParameterDeclaration) {
fType= CPPVisitor.createType((ICPPASTParameterDeclaration) parent, false);
break;
}
parent= parent.getParent();
}
}
return fType;
}
@Override
public boolean isStatic() {
return false;
}
@Override
public String[] getQualifiedName() {
return new String[] { getName() };
}
@Override
public char[][] getQualifiedNameCharArray() {
return new char[][] { getNameCharArray() };
}
@Override
public boolean isGloballyQualified() {
return false;
}
@Override
public boolean isExtern() {
//7.1.1-5 extern can not be used in the declaration of a parameter
return false;
}
@Override
public boolean isMutable() {
//7.1.1-8 mutable can only apply to class members
return false;
}
@Override
public boolean isConstexpr() {
return false;
}
@Override
public boolean isAuto() {
return hasStorageClass(IASTDeclSpecifier.sc_auto);
}
@Override
public boolean isRegister() {
return hasStorageClass(IASTDeclSpecifier.sc_register);
}
private boolean hasStorageClass(int storage) {
IASTNode parent = fDeclaration.getParent();
while (parent != null && !(parent instanceof IASTParameterDeclaration))
parent = parent.getParent();
if (parent != null) {
IASTDeclSpecifier declSpec = ((IASTParameterDeclaration) parent).getDeclSpecifier();
if (declSpec.getStorageClass() == storage)
return true;
}
return false;
}
@Override
public boolean hasDefaultValue() {
return false;
}
@Override
public IValue getDefaultValue() {
return null;
}
@Override
public ILinkage getLinkage() {
return Linkage.CPP_LINKAGE;
}
@Override
public boolean isExternC() {
return false;
}
@Override
public String toString() {
String name = getName();
return name.length() != 0 ? name : "<unnamed>"; //$NON-NLS-1$
}
@Override
public IBinding getOwner() {
IASTNode node= fDeclaration;
while (node != null && !(node instanceof ICPPASTLambdaExpression))
node= node.getParent();
if (node instanceof ICPPASTLambdaExpression) {
IType type= ((ICPPASTLambdaExpression) node).getExpressionType();
if (type instanceof IBinding) {
return (IBinding) type;
}
}
return null;
}
@Override
public IValue getInitialValue() {
return null;
}
}

View file

@ -26,6 +26,7 @@ import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.IValue;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLambdaExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType;
@ -277,6 +278,10 @@ public class CPPParameter extends PlatformObject implements ICPPParameter, ICPPI
ASTQueries.findAncestorWithType(fDeclarations[0], IASTFunctionDeclarator.class);
if (decl == null)
return null;
if (decl.getParent() instanceof ICPPASTLambdaExpression) {
CPPClosureType closure = (CPPClosureType) ((ICPPASTLambdaExpression) decl.getParent()).getExpressionType();
return closure.getFunctionCallOperator();
}
IASTName name= decl.getName();
return name != null ? name.resolveBinding() : null;
}
@ -299,9 +304,11 @@ public class CPPParameter extends PlatformObject implements ICPPParameter, ICPPI
}
if (node instanceof IASTFunctionDeclarator) {
IASTName funcName= ASTQueries.findInnermostDeclarator((IASTFunctionDeclarator) node).getName();
IBinding b= funcName.resolvePreBinding();
if (b instanceof ICPPInternalFunction) {
return ((ICPPInternalFunction) b).resolveParameter(this);
if (funcName != null) { // will be null for lambda declarator
IBinding b= funcName.resolvePreBinding();
if (b instanceof ICPPInternalFunction) {
return ((ICPPInternalFunction) b).resolveParameter(this);
}
}
}
return this;

View file

@ -163,6 +163,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceAlias;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespaceScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameter;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPParameterPackType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope;
@ -207,7 +208,6 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunction;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunctionTemplate;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPFunctionType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPLabel;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPLambdaExpressionParameter;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPMethod;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPMethodTemplate;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPNamespace;
@ -744,6 +744,15 @@ public class CPPVisitor extends ASTQueries {
return null;
}
private static int findParameterIndex(IASTParameterDeclaration param, IASTParameterDeclaration[] params) {
int i= 0;
for (; i < params.length; i++) {
if (params[i] == param)
return i;
}
return -1;
}
private static IBinding createBinding(IASTDeclarator declarator) {
IASTNode parent = findOutermostDeclarator(declarator).getParent();
declarator= findInnermostDeclarator(declarator);
@ -796,17 +805,18 @@ public class CPPVisitor extends ASTQueries {
final IASTNode dtorParent= findOutermostDeclarator(fdtor).getParent();
if (dtorParent instanceof ICPPASTLambdaExpression) {
return new CPPLambdaExpressionParameter(name);
CPPClosureType closure = (CPPClosureType)
((ICPPASTLambdaExpression) dtorParent).getExpressionType();
ICPPParameter[] paramBindings = closure.getParameters();
int index = findParameterIndex(param, fdtor.getParameters());
if (index >= 0 && index < paramBindings.length) {
return paramBindings[index];
}
}
if (dtorParent instanceof IASTDeclaration) {
IASTParameterDeclaration[] params = fdtor.getParameters();
int i= 0;
for (; i < params.length; i++) {
if (params[i] == param)
break;
}
return new CPPParameter(name, i);
int index = findParameterIndex(param, fdtor.getParameters());
return new CPPParameter(name, index);
}
return null;
} else if (parent instanceof ICPPASTTemplateDeclaration) {

View file

@ -63,8 +63,9 @@ public class EvalBinding extends CPPDependentEvaluation {
private int fParameterPosition;
/**
* The binding represented by this evaluation. For a function parameter binding may be computed
* lazily to avoid infinite recursion during unmarshalling of the evaluation. If #fBinding is
* {@code null}, {@link #fParameterOwner} is guaranteed to be not {@code null} and vice versa.
* lazily to avoid infinite recursion during unmarshalling of the evaluation. If
* {@link #fBinding} is {@code null}, {@link #fParameterOwner} is guaranteed to be not {@code null}
* and vice versa.
*/
private IBinding fBinding;
private final boolean fFixedType;