Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHansruedi Patzen2018-05-26 11:44:37 +0000
committerNathan Ridge2018-05-28 22:30:30 +0000
commit957dae8f4ea9069c9fa67e4e1082ff588bd2a5cb (patch)
treea6fd239bef83e0664aaabb48f1c5d3f97421def7
parent74c80478d95c44935f5c7f3f3956062d08dc3ae4 (diff)
downloadorg.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>
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/DOMParserTestSuite.java2
-rw-r--r--core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/cxx14/InitCaptureTests.java144
-rw-r--r--core/org.eclipse.cdt.core.tests/resources/rewrite/ASTWriterDeclarationTestSource.awts38
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTInitCapture.java36
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPNodeFactory.java5
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCapture.java64
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTCaptureBase.java38
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeclarator.java9
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTInitCapture.java140
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPNodeFactory.java6
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java64
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPSemantics.java17
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java63
-rw-r--r--core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/rewrite/astwriter/ExpressionWriter.java11
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);
}
}

Back to the top