diff options
author | Hansruedi Patzen | 2018-05-26 11:44:37 +0000 |
---|---|---|
committer | Nathan Ridge | 2018-05-28 22:30:30 +0000 |
commit | 957dae8f4ea9069c9fa67e4e1082ff588bd2a5cb (patch) | |
tree | a6fd239bef83e0664aaabb48f1c5d3f97421def7 | |
parent | 74c80478d95c44935f5c7f3f3956062d08dc3ae4 (diff) | |
download | org.eclipse.cdt-957dae8f4ea9069c9fa67e4e1082ff588bd2a5cb.tar.gz org.eclipse.cdt-957dae8f4ea9069c9fa67e4e1082ff588bd2a5cb.tar.xz org.eclipse.cdt-957dae8f4ea9069c9fa67e4e1082ff588bd2a5cb.zip |
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>
14 files changed, 555 insertions, 82 deletions
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java index 75cebea83b1..ab2d73a1ceb 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java @@ -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; diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/cxx14/InitCaptureTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/cxx14/InitCaptureTests.java new file mode 100644 index 00000000000..afbd1e18e72 --- /dev/null +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/cxx14/InitCaptureTests.java @@ -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_); + } +} diff --git a/core/org.eclipse.cdt.core.tests/resources/rewrite/ASTWriterDeclarationTestSource.awts b/core/org.eclipse.cdt.core.tests/resources/rewrite/ASTWriterDeclarationTestSource.awts index b0ded6c335e..9958fc479cb 100644 --- a/core/org.eclipse.cdt.core.tests/resources/rewrite/ASTWriterDeclarationTestSource.awts +++ b/core/org.eclipse.cdt.core.tests/resources/rewrite/ASTWriterDeclarationTestSource.awts @@ -122,4 +122,40 @@ template<typename... T> struct Tpl template<typename... T> void foo(Tpl<T...>) { -}
\ No newline at end of file +} + +//!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}] { + } + ; +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTInitCapture.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTInitCapture.java new file mode 100644 index 00000000000..8d31e3c9f1d --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTInitCapture.java @@ -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); +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNodeFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNodeFactory.java index 819c020599e..1abf3349655 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNodeFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNodeFactory.java @@ -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); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCapture.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCapture.java index ea495c2c055..330ba573603 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCapture.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCapture.java @@ -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); } @@ -47,28 +42,21 @@ public class CPPASTCapture extends ASTNode implements ICPPASTCapture { } @Override - public boolean isByReference() { - return fByReference; - } - - @Override - public boolean isPackExpansion() { - return fPackExpansion; - } - - @Override public IASTName getIdentifier() { return fIdentifier; } @Override 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; - } + if (visitor.shouldVisitCaptures) { + switch (visitor.visit(this)) { + case ASTVisitor.PROCESS_ABORT: + return false; + case ASTVisitor.PROCESS_SKIP: + return true; + default: + break; + } } if (fIdentifier != null && !fIdentifier.accept(visitor)) @@ -77,8 +65,8 @@ public class CPPASTCapture extends ASTNode implements ICPPASTCapture { if (visitor.shouldVisitCaptures && visitor.leave(this) == ASTVisitor.PROCESS_ABORT) return false; - return true; - } + return true; + } @Override public void setIdentifier(IASTName identifier) { @@ -91,24 +79,22 @@ public class CPPASTCapture extends ASTNode implements ICPPASTCapture { } @Override - public void setIsByReference(boolean value) { - assertNotFrozen(); - fByReference= value; + public int getRoleForName(IASTName name) { + if (name == fIdentifier) { + return r_reference; + } + return r_unclear; } @Override - public void setIsPackExpansion(boolean val) { - assertNotFrozen(); - fPackExpansion= val; + public boolean isByReference() { + return fByReference; } @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; + public void setIsByReference(boolean value) { + assertNotFrozen(); + fByReference = value; } + } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCaptureBase.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCaptureBase.java new file mode 100644 index 00000000000..21ec86f5e7f --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCaptureBase.java @@ -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; + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeclarator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeclarator.java index d1fb569acc1..b380d67812a 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeclarator.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeclarator.java @@ -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(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTInitCapture.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTInitCapture.java new file mode 100644 index 00000000000..8b21ff842dc --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTInitCapture.java @@ -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); + } +} diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java index acfc73d7c22..e2d0ab790c4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java @@ -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; @@ -262,6 +263,11 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory { } @Override + public ICPPASTInitCapture newInitCapture(ICPPASTDeclarator declarator) { + return new CPPASTInitCapture(declarator); + } + + @Override public IASTCaseStatement newCaseStatement(IASTExpression expr) { return new CPPASTCaseStatement(expr); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java index 46cee018422..575083028c7 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java @@ -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 diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java index 83f90595a57..246cbe9630c 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java @@ -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) { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java index be998e398eb..370a74566f1 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java @@ -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); @@ -2094,7 +2100,16 @@ 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(); } @@ -2191,7 +2208,28 @@ 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; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/ExpressionWriter.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/ExpressionWriter.java index 1d75f4d6658..7816cef8d35 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/ExpressionWriter.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/ExpressionWriter.java @@ -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; @@ -571,10 +572,14 @@ public class ExpressionWriter extends NodeWriter{ if (capture.capturesThisPointer()) { scribe.print(THIS); } else { - if (capture.isByReference()) { - scribe.print(AMPERSAND_OP); + if (capture instanceof ICPPASTInitCapture) { + ((ICPPASTInitCapture) capture).getDeclarator().accept(visitor); + } else { + if (capture.isByReference()) { + scribe.print(AMPERSAND_OP); + } + capture.getIdentifier().accept(visitor); } - capture.getIdentifier().accept(visitor); } } |