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

Bug 413527: [C++14] Support Lambda init-captures

This patch adds parsing and semantic support for lambda init-captures.

Change-Id: Ia5f39ea6f8780ecd6a9685f432bcbdf39e09c82a
Signed-off-by: Hansruedi Patzen <hansruedi.patzen@hsr.ch>
This commit is contained in:
Hansruedi Patzen 2018-05-26 13:44:37 +02:00 committed by Nathan Ridge
parent 74c80478d9
commit 957dae8f4e
14 changed files with 556 additions and 83 deletions

View file

@ -14,6 +14,7 @@
package org.eclipse.cdt.core.parser.tests.ast2;
import org.eclipse.cdt.core.parser.tests.ast2.cxx14.GenericLambdaTests;
import org.eclipse.cdt.core.parser.tests.ast2.cxx14.InitCaptureTests;
import org.eclipse.cdt.core.parser.tests.ast2.cxx14.ReturnTypeDeductionTests;
import org.eclipse.cdt.core.parser.tests.ast2.cxx14.VariableTemplateTests;
import org.eclipse.cdt.core.parser.tests.ast2.cxx17.TemplateAutoTests;
@ -65,6 +66,7 @@ public class DOMParserTestSuite extends TestCase {
suite.addTest(VariableTemplateTests.suite());
suite.addTestSuite(ReturnTypeDeductionTests.class);
suite.addTestSuite(GenericLambdaTests.class);
suite.addTestSuite(InitCaptureTests.class);
// C++17 tests
suite.addTest(TemplateAutoTests.suite());
return suite;

View file

@ -0,0 +1,144 @@
/*******************************************************************************
* Copyright (c) 2018 Institute for Software, HSR Hochschule fuer Technik
* Rapperswil, University of applied sciences 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:
* Hansruedi Patzen (IFS)
*******************************************************************************/
package org.eclipse.cdt.core.parser.tests.ast2.cxx14;
import org.eclipse.cdt.core.parser.tests.ast2.AST2CPPTestBase;
/**
* AST tests for C++14 lambda init captures.
*/
public class InitCaptureTests extends AST2CPPTestBase {
// int main() {
// [var1 { 3 }] { }();
// }
public void testLambdaInitCaptures_413527_1a() throws Exception {
parseAndCheckBindings();
}
// int main() {
// int var2 {};
// [var1 { 3 }, var2] { }();
// }
public void testLambdaInitCaptures_413527_1b() throws Exception {
parseAndCheckBindings();
}
// int main() {
// int var2 {};
// [var1 { 3 }, var2] { }();
// }
public void testLambdaInitCaptures_413527_1c() throws Exception {
BindingAssertionHelper helper = getAssertionHelper();
helper.assertVariableType("var2", CommonCPPTypes.int_);
helper.assertVariableType("var1", CommonCPPTypes.int_);
}
// int main() {
// [var1(3)] { }();
// }
public void testLambdaInitCaptures_413527_2a() throws Exception {
parseAndCheckBindings();
}
// int main() {
// int var2 { };
// [var1(3), var2] { }();
// }
public void testLambdaInitCaptures_413527_2b() throws Exception {
parseAndCheckBindings();
}
// int main() {
// int var2 { };
// [var1(3), var2] { }();
// }
public void testLambdaInitCaptures_413527_2c() throws Exception {
BindingAssertionHelper helper = getAssertionHelper();
helper.assertVariableType("var2", CommonCPPTypes.int_);
helper.assertVariableType("var1", CommonCPPTypes.int_);
}
// int main() {
// int var2 { };
// [var1( { 3, 3 } ), var2] { }();
// }
public void testLambdaInitCaptures_413527_2d() throws Exception {
BindingAssertionHelper helper = getAssertionHelper();
helper.assertVariableType("var2", CommonCPPTypes.int_);
// #include <initalizer_list> missing
helper.assertVariableTypeProblem("var1");
}
// int main() {
// [var1 = 3] { }();
// }
public void testLambdaInitCaptures_413527_3a() throws Exception {
parseAndCheckBindings();
}
// int main() {
// int var2 { };
// [var1 = 3, var2] { }();
// }
public void testLambdaInitCaptures_413527_3b() throws Exception {
parseAndCheckBindings();
}
// int main() {
// int var2 { };
// [var1 = 3, var2] { }();
// }
public void testLambdaInitCaptures_413527_3c() throws Exception {
BindingAssertionHelper helper = getAssertionHelper();
helper.assertVariableType("var2", CommonCPPTypes.int_);
helper.assertVariableType("var1", CommonCPPTypes.int_);
}
// struct S {
// int i;
// int j;
// };
// int main() {
// int var2 { };
// [var1 = { 3, 4 }, var2] { }();
// }
public void testLambdaInitCaptures_413527_3d() throws Exception {
BindingAssertionHelper helper = getAssertionHelper();
helper.assertVariableType("var2", CommonCPPTypes.int_);
// #include <initalizer_list> missing
helper.assertVariableTypeProblem("var1");
}
// int main() {
// [var1 { 3 }] {
// auto var3 = var1;
// }();
// }
public void testLambdaInitCaptures_413527_4a() throws Exception {
parseAndCheckBindings();
BindingAssertionHelper helper = getAssertionHelper();
helper.assertVariableType("var1", CommonCPPTypes.int_);
helper.assertVariableType("var3", CommonCPPTypes.int_);
}
// int main() {
// [var1 { 3 }] {
// var1++;
// }();
// }
public void testLambdaInitCaptures_413527_4b() throws Exception {
parseAndCheckBindings();
BindingAssertionHelper helper = getAssertionHelper();
helper.assertVariableType("var1", CommonCPPTypes.int_);
}
}

View file

@ -123,3 +123,39 @@ template<typename... T>
void foo(Tpl<T...>)
{
}
//!Lambda init capture equals
//%CPP
int main()
{
[c = {3, 3}] {
}
;
}
//!Lambda init capture braces
//%CPP
int main()
{
[c{3, 3}] {
}
;
}
//!Lambda init capture parenthesis
//%CPP
int main()
{
[c({3, 3})] {
}
;
}
//!Lambda init equals by ref
//%CPP
int main()
{
[&c = {3, 3}] {
}
;
}

View file

@ -0,0 +1,36 @@
/*******************************************************************************
* Copyright (c) 2018 Institute for Software, HSR Hochschule fuer Technik
* Rapperswil, University of applied sciences 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:
* Hansruedi Patzen (IFS) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.dom.ast.cpp;
import org.eclipse.cdt.core.dom.ast.ASTNodeProperty;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
/**
* Init capture for a lambda expression, introduced in C++14.
*
* @since 6.5
* @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented by clients.
*/
public interface ICPPASTInitCapture extends ICPPASTCapture, IASTDeclaration {
ASTNodeProperty DECLARATOR = new ASTNodeProperty("ICPPASTInitCapture - DECLARATOR [IASTDeclarator]"); //$NON-NLS-1$
@Override
ICPPASTInitCapture copy();
@Override
ICPPASTInitCapture copy(CopyStyle style);
ICPPASTDeclarator getDeclarator();
void setDeclarator(ICPPASTDeclarator declarator);
}

View file

@ -105,6 +105,11 @@ public interface ICPPNodeFactory extends INodeFactory {
*/
public ICPPASTCapture newCapture();
/**
* @since 6.5
*/
public ICPPASTInitCapture newInitCapture(ICPPASTDeclarator declarator);
@Override
public ICPPASTCastExpression newCastExpression(int operator, IASTTypeId typeId, IASTExpression operand);

View file

@ -12,15 +12,12 @@ package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCapture;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
/**
* Implementation for captures.
*/
public class CPPASTCapture extends ASTNode implements ICPPASTCapture {
public class CPPASTCapture extends CPPASTCaptureBase {
private boolean fByReference;
private boolean fPackExpansion;
private IASTName fIdentifier;
public CPPASTCapture() {
@ -34,10 +31,8 @@ public class CPPASTCapture extends ASTNode implements ICPPASTCapture {
@Override
public CPPASTCapture copy(CopyStyle style) {
final CPPASTCapture copy = new CPPASTCapture();
if (fIdentifier != null)
copy.setIdentifier(fIdentifier.copy(style));
copy.fByReference = fByReference;
copy.fPackExpansion = fPackExpansion;
copy.setIsByReference(fByReference);
copy.setIdentifier(fIdentifier == null ? null : fIdentifier.copy(style));
return copy(copy, style);
}
@ -46,16 +41,6 @@ public class CPPASTCapture extends ASTNode implements ICPPASTCapture {
return fIdentifier == null;
}
@Override
public boolean isByReference() {
return fByReference;
}
@Override
public boolean isPackExpansion() {
return fPackExpansion;
}
@Override
public IASTName getIdentifier() {
return fIdentifier;
@ -65,9 +50,12 @@ public class CPPASTCapture extends ASTNode implements ICPPASTCapture {
public boolean accept(ASTVisitor visitor) {
if (visitor.shouldVisitCaptures) {
switch (visitor.visit(this)) {
case ASTVisitor.PROCESS_ABORT: return false;
case ASTVisitor.PROCESS_SKIP: return true;
default: break;
case ASTVisitor.PROCESS_ABORT:
return false;
case ASTVisitor.PROCESS_SKIP:
return true;
default:
break;
}
}
@ -90,25 +78,23 @@ public class CPPASTCapture extends ASTNode implements ICPPASTCapture {
fIdentifier= identifier;
}
@Override
public void setIsByReference(boolean value) {
assertNotFrozen();
fByReference= value;
}
@Override
public void setIsPackExpansion(boolean val) {
assertNotFrozen();
fPackExpansion= val;
}
@Override
public int getRoleForName(IASTName name) {
if (name == fIdentifier) {
// Treat the capture as a reference to the captured variable.
// This choice may be revisited when C++14 init-captures are implemented.
return r_reference;
}
return r_unclear;
}
@Override
public boolean isByReference() {
return fByReference;
}
@Override
public void setIsByReference(boolean value) {
assertNotFrozen();
fByReference = value;
}
}

View file

@ -0,0 +1,38 @@
/*******************************************************************************
* Copyright (c) 2018 Institute for Software, HSR Hochschule fuer Technik
* Rapperswil, University of applied sciences 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:
* Hansruedi Patzen (IFS) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCapture;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
/**
* Base class for C++ Lambda Captures
*/
public abstract class CPPASTCaptureBase extends ASTNode implements ICPPASTCapture {
private boolean fPackExpansion;
protected <T extends CPPASTCaptureBase> T copy(T copy, CopyStyle style) {
copy.setIsPackExpansion(fPackExpansion);
return super.copy(copy, style);
}
@Override
public boolean isPackExpansion() {
return fPackExpansion;
}
@Override
public void setIsPackExpansion(boolean val) {
assertNotFrozen();
fPackExpansion = val;
}
}

View file

@ -136,6 +136,15 @@ public class CPPASTDeclarator extends CPPASTAttributeOwner implements ICPPASTDec
}
}
/**
* Remove a pointer operator from the pointer operators
* @param operator Pointer operator to be removed
*/
public void removePointerOperator(IASTPointerOperator operator) {
assertNotFrozen();
ArrayUtil.remove(pointerOps, operator);
}
@Override
public void setNestedDeclarator(IASTDeclarator nested) {
assertNotFrozen();

View file

@ -0,0 +1,140 @@
/*******************************************************************************
* Copyright (c) 2018 Institute for Software, HSR Hochschule fuer Technik
* Rapperswil, University of applied sciences 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:
* Hansruedi Patzen (IFS) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.cpp;
import java.util.Objects;
import org.eclipse.cdt.core.dom.ast.ASTVisitor;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTPointerOperator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCapture;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitCapture;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTReferenceOperator;
/**
* Implementation for init captures.
*/
public class CPPASTInitCapture extends CPPASTCaptureBase implements ICPPASTInitCapture {
private ICPPASTDeclarator fDeclarator;
public CPPASTInitCapture(ICPPASTDeclarator declarator) {
setDeclarator(declarator);
}
@Override
public CPPASTInitCapture copy() {
return copy(CopyStyle.withoutLocations);
}
@Override
public CPPASTInitCapture copy(CopyStyle style) {
final CPPASTInitCapture copy = new CPPASTInitCapture((ICPPASTDeclarator) fDeclarator.copy(style));
copy.setIsByReference(false);
return copy(copy, style);
}
@Override
public boolean accept(ASTVisitor visitor) {
if (visitor.shouldVisitCaptures) {
switch (visitor.visit((ICPPASTCapture) this)) {
case ASTVisitor.PROCESS_ABORT:
return false;
case ASTVisitor.PROCESS_SKIP:
return true;
default:
break;
}
}
if (visitor.shouldVisitDeclarations) {
switch (visitor.visit((IASTDeclaration) this)) {
case ASTVisitor.PROCESS_ABORT:
return false;
case ASTVisitor.PROCESS_SKIP:
return true;
}
}
if (fDeclarator != null && !fDeclarator.accept(visitor)) {
return false;
}
if (visitor.shouldVisitDeclarations && visitor.leave((IASTDeclaration) this) == ASTVisitor.PROCESS_ABORT) {
return false;
}
if (visitor.shouldVisitCaptures && visitor.leave((ICPPASTCapture) this) == ASTVisitor.PROCESS_ABORT) {
return false;
}
return true;
}
@Override
public boolean capturesThisPointer() {
return false;
}
@Override
public int getRoleForName(IASTName name) {
if (name == fDeclarator.getName()) {
return r_declaration;
}
return r_unclear;
}
@Override
public boolean isByReference() {
IASTPointerOperator[] pointerOperators = fDeclarator.getPointerOperators();
return pointerOperators.length == 1 && pointerOperators[0] instanceof ICPPASTReferenceOperator;
}
@Override
public void setIsByReference(boolean value) {
assertNotFrozen();
boolean isReferenceCapture = isByReference();
if (value && !isReferenceCapture) {
fDeclarator.addPointerOperator(CPPNodeFactory.getDefault().newReferenceOperator(false));
} else if (!value && isReferenceCapture) {
// Use non API removePointerOperator
((CPPASTDeclarator) fDeclarator).removePointerOperator(fDeclarator.getPointerOperators()[0]);
}
}
@Override
public ICPPASTDeclarator getDeclarator() {
return fDeclarator;
}
@Override
public void setDeclarator(ICPPASTDeclarator declarator) {
assertNotFrozen();
Objects.requireNonNull(declarator, "An init capture declarator must not be null."); //$NON-NLS-1$
fDeclarator = declarator;
fDeclarator.setParent(this);
fDeclarator.setPropertyInParent(DECLARATOR);
}
@Override
public IASTName getIdentifier() {
return fDeclarator.getName();
}
@Override
public void setIdentifier(IASTName identifier) {
assertNotFrozen();
Objects.requireNonNull(identifier, "An init capture must have an identifier."); //$NON-NLS-1$
fDeclarator.setName(identifier);
}
}

View file

@ -90,6 +90,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionWithTryBlock;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTIfStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitCapture;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerClause;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLambdaExpression;
@ -261,6 +262,11 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory {
return new CPPASTCapture();
}
@Override
public ICPPASTInitCapture newInitCapture(ICPPASTDeclarator declarator) {
return new CPPASTInitCapture(declarator);
}
@Override
public IASTCaseStatement newCaseStatement(IASTExpression expr) {
return new CPPASTCaseStatement(expr);

View file

@ -106,6 +106,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator.RefQualifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionWithTryBlock;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTIfStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitCapture;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerClause;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLambdaExpression;
@ -2102,28 +2103,56 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
return setRange(lambdaExpr, offset, calculateEndOffset(body));
}
private ICPPASTInitCapture createInitCapture(IASTName identifier, IASTInitializer initializer, boolean isReference, int offset)
throws EndOfFileException, BacktrackException {
ICPPASTDeclarator declarator = getNodeFactory().newDeclarator(identifier);
declarator.setInitializer(initializer);
if (isReference) {
declarator.addPointerOperator(getNodeFactory().newReferenceOperator(false));
}
setRange(declarator, offset, calculateEndOffset(initializer));
ICPPASTInitCapture initCapture = getNodeFactory().newInitCapture(declarator);
return setRange(initCapture, offset, calculateEndOffset(initializer));
}
private ICPPASTCapture capture() throws EndOfFileException, BacktrackException {
final int offset= LA().getOffset();
final ICPPASTCapture result = getNodeFactory().newCapture();
final int offset = LA().getOffset();
ICPPASTCapture result = getNodeFactory().newCapture();
boolean referenceCapture = false;
switch (LT(1)) {
case IToken.t_this:
return setRange(result, offset, consume().getEndOffset());
case IToken.tAMPER:
consume();
result.setIsByReference(true);
referenceCapture = true;
break;
}
final IASTName identifier= identifier();
final IASTName identifier = identifier();
result.setIdentifier(identifier);
result.setIsByReference(referenceCapture);
setRange(result, offset, calculateEndOffset(identifier));
switch(LT(1)) {
case IToken.tASSIGN:
result = createInitCapture(identifier, equalsInitalizerClause(false), referenceCapture, offset);
break;
case IToken.tLBRACE:
case IToken.tLPAREN:
result = createInitCapture(identifier, bracedOrCtorStyleInitializer(), referenceCapture, offset);
break;
}
if (LT(1) == IToken.tELLIPSIS) {
// Note this will probably change with C++20 such that the
// pack expansion of a CPPASTInitCapture will be part of the IASTDeclarator
// and not the capture. [See: P0780R2]
result.setIsPackExpansion(true);
return setRange(result, offset, consume().getEndOffset());
}
return setRange(result, offset, calculateEndOffset(identifier));
return result;
}
protected IASTExpression specialCastExpression(int kind) throws EndOfFileException, BacktrackException {
@ -3947,6 +3976,20 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
}
}
private IASTEqualsInitializer equalsInitalizerClause(boolean allowSkipping)
throws EndOfFileException, BacktrackException {
// Check for deleted or defaulted function syntax.
final int lt2 = LTcatchEOF(2);
if (lt2 == IToken.t_delete || lt2 == IToken.t_default) {
return null;
}
int offset = consume(IToken.tASSIGN).getOffset();
IASTInitializerClause initClause = initClause(allowSkipping);
IASTEqualsInitializer initExpr = getNodeFactory().newEqualsInitializer(initClause);
return setRange(initExpr, offset, calculateEndOffset(initClause));
}
/**
* initializer:
* brace-or-equal-initializer
@ -3963,16 +4006,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
// = initializer-clause
if (lt1 == IToken.tASSIGN) {
// Check for deleted or defaulted function syntax.
final int lt2= LTcatchEOF(2);
if (lt2 == IToken.t_delete || lt2 == IToken.t_default)
return null;
int offset= consume().getOffset();
final boolean allowSkipping = LT(1) == IToken.tLBRACE && specifiesArray(dtor);
IASTInitializerClause initClause = initClause(allowSkipping);
IASTEqualsInitializer initExpr= getNodeFactory().newEqualsInitializer(initClause);
return setRange(initExpr, offset, calculateEndOffset(initClause));
return equalsInitalizerClause(LTcatchEOF(2) == IToken.tLBRACE && specifiesArray(dtor));
}
// braced-init-list

View file

@ -104,6 +104,7 @@ import org.eclipse.cdt.core.dom.ast.IType;
import org.eclipse.cdt.core.dom.ast.ITypedef;
import org.eclipse.cdt.core.dom.ast.IVariable;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTAliasDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCapture;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCatchHandler;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier;
@ -121,6 +122,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTForStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTIfStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitCapture;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerClause;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLambdaExpression;
@ -1582,9 +1584,18 @@ public class CPPSemantics {
ICPPASTFunctionDeclarator dtor = (ICPPASTFunctionDeclarator) ((IASTFunctionDefinition) p).getDeclarator();
nodes = dtor.getParameters();
} else if (p instanceof ICPPASTLambdaExpression) {
ICPPASTFunctionDeclarator dtor = ((ICPPASTLambdaExpression) p).getDeclarator();
if (dtor != null) {
nodes = dtor.getParameters();
ICPPASTLambdaExpression lambdaExpression = (ICPPASTLambdaExpression) p;
for (ICPPASTCapture capture : lambdaExpression.getCaptures()) {
if (capture instanceof ICPPASTInitCapture) {
IASTName name = capture.getIdentifier();
if (name != null) {
ASTInternal.addName(scope, name);
}
}
}
ICPPASTFunctionDeclarator lambdaDeclarator = lambdaExpression.getDeclarator();
if (lambdaDeclarator != null) {
nodes = lambdaDeclarator.getParameters();
}
}
if (p instanceof ICPPASTCatchHandler) {

View file

@ -118,6 +118,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator.RefQualifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTIfStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitCapture;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerClause;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitializerList;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLambdaExpression;
@ -270,7 +271,7 @@ public class CPPVisitor extends ASTQueries {
if (parent instanceof IASTNamedTypeSpecifier ||
parent instanceof ICPPASTBaseSpecifier ||
parent instanceof ICPPASTConstructorChainInitializer ||
parent instanceof ICPPASTCapture ||
(parent instanceof ICPPASTCapture && !(parent instanceof ICPPASTInitCapture)) ||
name.getPropertyInParent() == ICPPASTNamespaceAlias.MAPPING_NAME) {
if (name.getLookupKey().length == 0)
return null;
@ -755,6 +756,11 @@ public class CPPVisitor extends ASTQueries {
private static IBinding createBinding(IASTDeclarator declarator) {
IASTNode parent = findOutermostDeclarator(declarator).getParent();
if (parent instanceof ICPPASTInitCapture) {
return new CPPVariable(declarator.getName());
}
declarator= findInnermostDeclarator(declarator);
final IASTDeclarator typeRelevantDtor= findTypeRelevantDeclarator(declarator);
@ -2095,6 +2101,15 @@ public class CPPVisitor extends ASTQueries {
return null;
}
public static IType createType(ICPPASTInitCapture capture) {
IASTDeclarator declarator = capture.getDeclarator();
ICPPASTInitializerClause initClause = getAutoInitClauseForDeclarator(declarator);
if (initClause == null) {
return ProblemType.CANNOT_DEDUCE_AUTO_TYPE;
}
return createAutoType(initClause.getEvaluation(), null, declarator);
}
public static IType createType(IASTDeclarator declarator) {
// Resolve placeholders by default.
return createType(declarator, RESOLVE_PLACEHOLDERS);
@ -2121,6 +2136,8 @@ public class CPPVisitor extends ASTQueries {
final ICPPASTTypeId typeId = (ICPPASTTypeId) parent;
declSpec = typeId.getDeclSpecifier();
isPackExpansion= typeId.isPackExpansion();
} else if (parent instanceof ICPPASTInitCapture) {
return createType((ICPPASTInitCapture) parent);
} else {
throw new IllegalArgumentException();
}
@ -2192,6 +2209,27 @@ public class CPPVisitor extends ASTQueries {
return ProblemType.CANNOT_DEDUCE_AUTO_TYPE;
}
private static ICPPASTInitializerClause getAutoInitClauseForDeclarator(IASTDeclarator declarator) {
IASTInitializer initClause= declarator.getInitializer();
if (initClause instanceof IASTEqualsInitializer) {
return (ICPPASTInitializerClause) ((IASTEqualsInitializer) initClause).getInitializerClause();
} else if (initClause instanceof ICPPASTConstructorInitializer) {
IASTInitializerClause[] arguments = ((ICPPASTConstructorInitializer) initClause).getArguments();
if (arguments.length == 1) {
return (ICPPASTInitializerClause) arguments[0];
}
} else if (initClause instanceof ICPPASTInitializerClause) {
if (initClause instanceof ICPPASTInitializerList) {
IASTInitializerClause[] clauses = ((ICPPASTInitializerList) initClause).getClauses();
if (clauses.length == 1) {
return (ICPPASTInitializerClause) clauses[0];
}
}
return (ICPPASTInitializerClause) initClause;
}
return null;
}
private static IType createAutoType(final IASTDeclSpecifier declSpec, IASTDeclarator declarator,
int flags, PlaceholderKind placeholderKind) {
IType cannotDeduce = placeholderKind == PlaceholderKind.Auto ?
@ -2271,24 +2309,7 @@ public class CPPVisitor extends ASTQueries {
// Non-static auto-typed class members are not allowed.
return ProblemType.AUTO_FOR_NON_STATIC_FIELD;
} else {
IASTInitializer initClause= declarator.getInitializer();
if (initClause instanceof IASTEqualsInitializer) {
autoInitClause= (ICPPASTInitializerClause) ((IASTEqualsInitializer) initClause).getInitializerClause();
} else if (initClause instanceof ICPPASTConstructorInitializer) {
IASTInitializerClause[] arguments = ((ICPPASTConstructorInitializer) initClause).getArguments();
if (arguments.length == 1)
autoInitClause = (ICPPASTInitializerClause) arguments[0];
} else if (initClause instanceof ICPPASTInitializerClause) {
if (initClause instanceof ICPPASTInitializerList) {
IASTInitializerClause[] clauses = ((ICPPASTInitializerList) initClause).getClauses();
if (clauses.length == 1) {
autoInitClause = (ICPPASTInitializerClause) clauses[0];
}
}
if (autoInitClause == null) {
autoInitClause= (ICPPASTInitializerClause) initClause;
}
}
autoInitClause = getAutoInitClauseForDeclarator(declarator);
}
if (autoInitClause == null) {
return cannotDeduce;

View file

@ -34,6 +34,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCapture;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCastExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFieldReference;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTInitCapture;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTLambdaExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTPackExpansionExpression;
@ -570,6 +571,9 @@ public class ExpressionWriter extends NodeWriter{
private void writeCapture(ICPPASTCapture capture) {
if (capture.capturesThisPointer()) {
scribe.print(THIS);
} else {
if (capture instanceof ICPPASTInitCapture) {
((ICPPASTInitCapture) capture).getDeclarator().accept(visitor);
} else {
if (capture.isByReference()) {
scribe.print(AMPERSAND_OP);
@ -577,6 +581,7 @@ public class ExpressionWriter extends NodeWriter{
capture.getIdentifier().accept(visitor);
}
}
}
private void writePackExpansionExpression(ICPPASTPackExpansionExpression expression) {
visitNodeIfNotNull(expression.getPattern());