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 5f17ae73f30..f1fe6b37975 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
@@ -20,6 +20,7 @@ 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.DeductionGuideTests;
import org.eclipse.cdt.core.parser.tests.ast2.cxx17.LambdaExpressionTests;
import org.eclipse.cdt.core.parser.tests.ast2.cxx17.StructuredBindingTests;
import org.eclipse.cdt.core.parser.tests.ast2.cxx17.TemplateAutoTests;
@@ -76,6 +77,7 @@ public class DOMParserTestSuite extends TestCase {
suite.addTest(TemplateAutoTests.suite());
suite.addTestSuite(LambdaExpressionTests.class);
suite.addTestSuite(StructuredBindingTests.class);
+ suite.addTestSuite(DeductionGuideTests.class);
return suite;
}
}
diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/cxx17/DeductionGuideTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/cxx17/DeductionGuideTests.java
new file mode 100644
index 00000000000..02705d96e5b
--- /dev/null
+++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/cxx17/DeductionGuideTests.java
@@ -0,0 +1,187 @@
+/*******************************************************************************
+ * Copyright (c) 2018, Institute for Software 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:
+ * Felix Morgner - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.core.parser.tests.ast2.cxx17;
+
+import static org.hamcrest.Matchers.arrayWithSize;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasToString;
+import static org.hamcrest.Matchers.is;
+
+import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
+import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
+import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeductionGuide;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateDeclaration;
+import org.eclipse.cdt.core.parser.tests.ast2.AST2CPPTestBase;
+import org.eclipse.cdt.core.parser.util.ArrayUtil;
+import org.hamcrest.MatcherAssert;
+
+public class DeductionGuideTests extends AST2CPPTestBase {
+
+ private static ICPPASTDeductionGuide firstGuide(IASTDeclaration[] array) {
+ return (ICPPASTDeductionGuide) ArrayUtil.filter(array, d -> d instanceof ICPPASTDeductionGuide)[0];
+ }
+
+ // template
+ * e.g:
+ *
+ *
+ * SomeTemplateName(int) -> SomeTemplateName<float>;
+ *
+ * template<typename I>
+ * SomeTemplateName(I, I) -> SomeTemplateName<typename std::iterator_traits<I>::value_type>;
+ *
+ *
TEMPLATE_NAME
represents the relationship between an
+ * ICPPASTDeductionGuide
and it's nested
+ * IASTName
.
+ */
+ static final ASTNodeProperty TEMPLATE_NAME = new ASTNodeProperty(
+ "ICPPASTDeductionGuide.TEMPLATE_NAME - IASTName for ICPPASTDeductionGuide"); //$NON-NLS-1$
+
+ /**
+ * TEMPLATE_ID
represents the relationship between an
+ * ICPPASTDeductionGuide
and it's nested
+ * ICPPASTTemplateId
.
+ */
+ static final ASTNodeProperty TEMPLATE_ID = new ASTNodeProperty(
+ "ICPPASTDeductionGuide.TEMPLATE_ID - ICPPASTTemplateId for ICPPASTDeductionGuide"); //$NON-NLS-1$
+
+ /**
+ * PARAMETER
represents the relationship between an
+ * ICPPASTDeductionGuide
and it's nested
+ * IASTParameterDeclaration
.
+ */
+ public final static ASTNodeProperty PARAMETER = new ASTNodeProperty(
+ "ICPPASTDeductionGuide.PARAMETER - IASTParameterDeclaration for ICPPASTDeductionGuide"); //$NON-NLS-1$
+
+ /**
+ * Check if the deduction guide was declared as 'explicit'.
+ */
+ boolean isExplicit();
+
+ /**
+ * Set whether or not the deduction guide is marked explicit
+ */
+ void setExplicit(boolean isExplict);
+
+ /**
+ * Get the name of the template type the deduction guide refers to
+ */
+ IASTName getTemplateName();
+
+ /**
+ * Set the name of the template type the deduction guide refers to
+ */
+ void setTemplateName(IASTName name);
+
+ /**
+ * Get the template id of the deduction guide
+ */
+ ICPPASTTemplateId getSimpleTemplateId();
+
+ /**
+ * Set the template id of the deduction guide
+ */
+ void setSimpleTemplateId(ICPPASTTemplateId id);
+
+ @Override
+ public ICPPASTDeductionGuide copy();
+
+ @Override
+ public ICPPASTDeductionGuide copy(CopyStyle style);
+
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTFunctionDeclarator.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTFunctionDeclarator.java
index e2be17585fd..3a6d6a297a8 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTFunctionDeclarator.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTFunctionDeclarator.java
@@ -29,7 +29,8 @@ import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPEvaluation;
* @noimplement This interface is not intended to be implemented by clients.
* @noextend This interface is not intended to be extended by clients.
*/
-public interface ICPPASTFunctionDeclarator extends IASTStandardFunctionDeclarator, ICPPASTDeclarator {
+public interface ICPPASTFunctionDeclarator
+ extends IASTStandardFunctionDeclarator, ICPPASTDeclarator, ICPPASTParameterListOwner {
/**
* @since 5.9
*/
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTParameterListOwner.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTParameterListOwner.java
new file mode 100644
index 00000000000..2fb01c1f04f
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTParameterListOwner.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2018, Institute for Software 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:
+ * Felix Morgner - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.core.dom.ast.cpp;
+
+import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
+
+/**
+ * Internal interface to describe the ability of having a parameter list
+ * @since 6.11
+ */
+public interface ICPPASTParameterListOwner {
+
+ /**
+ * Add a parameter to the parameter list of the parameter list owner.
+ */
+ public void addParameterDeclaration(IASTParameterDeclaration parameter);
+
+ /**
+ * Gets the parameter declarations for the parameter list owner
+ */
+ public IASTParameterDeclaration[] getParameters();
+
+ /**
+ * Set whether or not the parameter list owner takes a variable number of
+ * arguments.
+ */
+ public void setVarArgs(boolean value);
+
+ /**
+ * Check if the parameter list owner takes a variable number of arguments.
+ */
+ public boolean takesVarArgs();
+}
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/DeclarationOptions.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/DeclarationOptions.java
index 1c8285c104b..50376275f05 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/DeclarationOptions.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/DeclarationOptions.java
@@ -34,14 +34,15 @@ public class DeclarationOptions {
final public static int SINGLE_DTOR = 0x4000;
final public static int ALLOW_FUNCTION_DEFINITION = 0x8000;
final public static int NO_COMPOSITE_SPECIFIER = 0x10000;
+ final public static int ALLOW_DEDUCTION_GUIDE = 0x20000;
public static final DeclarationOptions GLOBAL = new DeclarationOptions(
- ALLOW_EMPTY_SPECIFIER | ALLOW_OPAQUE_ENUM | ALLOW_FUNCTION_DEFINITION),
+ ALLOW_EMPTY_SPECIFIER | ALLOW_OPAQUE_ENUM | ALLOW_FUNCTION_DEFINITION | ALLOW_DEDUCTION_GUIDE),
FUNCTION_STYLE_ASM = new DeclarationOptions(
ALLOW_EMPTY_SPECIFIER | NO_INITIALIZER | ALLOW_ABSTRACT | ALLOW_FUNCTION_DEFINITION),
C_MEMBER = new DeclarationOptions(ALLOW_BITFIELD | ALLOW_ABSTRACT),
CPP_MEMBER = new DeclarationOptions(ALLOW_EMPTY_SPECIFIER | ALLOW_BITFIELD | ALLOW_OPAQUE_ENUM
- | NO_CTOR_STYLE_INITIALIZER | ALLOW_FUNCTION_DEFINITION),
+ | NO_CTOR_STYLE_INITIALIZER | ALLOW_FUNCTION_DEFINITION | ALLOW_DEDUCTION_GUIDE),
LOCAL = new DeclarationOptions(ALLOW_OPAQUE_ENUM),
PARAMETER = new DeclarationOptions(ALLOW_ABSTRACT | ALLOW_PARAMETER_PACKS | REQUIRE_SIMPLE_NAME
| NO_BRACED_INITIALIZER | NO_CTOR_STYLE_INITIALIZER),
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousTemplateArgument.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousTemplateArgument.java
index 29590cb6bcc..5fc12dbdfd0 100644
--- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousTemplateArgument.java
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousTemplateArgument.java
@@ -47,6 +47,7 @@ public class CPPASTAmbiguousTemplateArgument extends ASTAmbiguousNode implements
fNodes = new ArrayList<>(2);
for (IASTNode node : nodes) {
if (node instanceof IASTTypeId || node instanceof IASTExpression) {
+ node.setParent(this);
fNodes.add(node);
} else {
Assert.isLegal(false, node == null ? "null" : node.getClass().getName()); //$NON-NLS-1$
diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeductionGuide.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeductionGuide.java
new file mode 100644
index 00000000000..edcfcddb3f4
--- /dev/null
+++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTDeductionGuide.java
@@ -0,0 +1,174 @@
+/*******************************************************************************
+ * Copyright (c) 2018, Institute for Software 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:
+ * Felix Morgner - initial API and implementation
+ *******************************************************************************/
+
+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.IASTNode;
+import org.eclipse.cdt.core.dom.ast.IASTParameterDeclaration;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeductionGuide;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
+import org.eclipse.cdt.core.parser.util.ArrayUtil;
+import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
+import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
+
+public class CPPASTDeductionGuide extends ASTNode implements ICPPASTDeductionGuide, IASTAmbiguityParent {
+
+ private IASTParameterDeclaration[] parameters;
+ private IASTName templateName;
+ private ICPPASTTemplateId templateId;
+ private boolean takesVarArgs;
+ private boolean isExplicit;
+
+ @Override
+ public boolean accept(ASTVisitor visitor) {
+ if (visitor.shouldVisitDeclarations) {
+ switch (visitor.visit(this)) {
+ case ASTVisitor.PROCESS_ABORT:
+ return false;
+ case ASTVisitor.PROCESS_SKIP:
+ return true;
+ default:
+ break;
+ }
+ }
+
+ if (!templateName.accept(visitor)) {
+ return false;
+ }
+
+ if (parameters != null) {
+ for (IASTParameterDeclaration parameter : parameters) {
+ if (parameter != null && !parameter.accept(visitor)) {
+ return false;
+ }
+ }
+ }
+
+ if (!templateId.accept(visitor)) {
+ return false;
+ }
+
+ if (visitor.shouldVisitDeclarations) {
+ switch (visitor.leave(this)) {
+ case ASTVisitor.PROCESS_ABORT:
+ return false;
+ case ASTVisitor.PROCESS_SKIP:
+ return true;
+ default:
+ break;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void addParameterDeclaration(IASTParameterDeclaration parameter) {
+ assertNotFrozen();
+ assert (parameter != null);
+ parameter.setParent(this);
+ parameter.setPropertyInParent(PARAMETER);
+ parameters = ArrayUtil.append(IASTParameterDeclaration.class, parameters, parameter);
+ }
+
+ @Override
+ public IASTParameterDeclaration[] getParameters() {
+ if (parameters == null) {
+ return ICPPASTParameterDeclaration.EMPTY_CPPPARAMETERDECLARATION_ARRAY;
+ }
+ return ArrayUtil.trim(parameters);
+ }
+
+ @Override
+ public void setVarArgs(boolean value) {
+ assertNotFrozen();
+ takesVarArgs = value;
+ }
+
+ @Override
+ public boolean takesVarArgs() {
+ return takesVarArgs;
+ }
+
+ @Override
+ public boolean isExplicit() {
+ return isExplicit;
+ }
+
+ @Override
+ public void setExplicit(boolean value) {
+ assertNotFrozen();
+ isExplicit = value;
+ }
+
+ @Override
+ public IASTName getTemplateName() {
+ return templateName;
+ }
+
+ @Override
+ public void setTemplateName(IASTName name) {
+ assertNotFrozen();
+ assert (name != null);
+ name.setParent(this);
+ name.setPropertyInParent(TEMPLATE_NAME);
+ templateName = name;
+ }
+
+ @Override
+ public ICPPASTTemplateId getSimpleTemplateId() {
+ return templateId;
+ }
+
+ @Override
+ public void setSimpleTemplateId(ICPPASTTemplateId id) {
+ assertNotFrozen();
+ assert (id != null);
+ id.setParent(this);
+ id.setPropertyInParent(TEMPLATE_ID);
+ templateId = id;
+ }
+
+ @Override
+ public ICPPASTDeductionGuide copy() {
+ return copy(CopyStyle.withoutLocations);
+ }
+
+ @Override
+ public ICPPASTDeductionGuide copy(CopyStyle style) {
+ CPPASTDeductionGuide copy = new CPPASTDeductionGuide();
+ copy.isExplicit = isExplicit;
+ copy.takesVarArgs = takesVarArgs;
+ copy.setTemplateName(templateName.copy(style));
+ copy.setSimpleTemplateId(templateId.copy(style));
+ if (parameters != null) {
+ for (IASTParameterDeclaration parameter : parameters) {
+ if (parameter != null) {
+ copy.addParameterDeclaration(parameter.copy(style));
+ }
+ }
+ }
+ return super.copy(copy, style);
+ }
+
+ @Override
+ public void replace(IASTNode child, IASTNode other) {
+ int indexOfChild = ArrayUtil.indexOfEqual(parameters, child);
+ if (indexOfChild > -1) {
+ other.setParent(this);
+ other.setPropertyInParent(PARAMETER);
+ child.setParent(null);
+ parameters[indexOfChild] = (IASTParameterDeclaration) other;
+ }
+ }
+}
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 58686ecc0b4..6e04ad4ac2f 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
@@ -127,6 +127,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTNewExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTOperatorName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTPackExpandable;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterDeclaration;
+import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTParameterListOwner;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTRangeBasedForStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTReferenceOperator;
@@ -3055,6 +3056,35 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
throwBacktrack(LA(1));
}
+ if (dtor instanceof ICPPASTFunctionDeclarator
+ && ((ICPPASTFunctionDeclarator) dtor).getTrailingReturnType() != null) {
+ if (declSpec instanceof IASTSimpleDeclSpecifier
+ && ((IASTSimpleDeclSpecifier) declSpec).getType() == IASTSimpleDeclSpecifier.t_unspecified) {
+ // we encountered something that looks like a ctor with trailing return type
+ CPPASTDeductionGuide guide = new CPPASTDeductionGuide();
+ guide.setExplicit(((ICPPASTDeclSpecifier) declSpec).isExplicit());
+ guide.setTemplateName(dtor.getName());
+ ICPPASTParameterDeclaration[] params = ((ICPPASTFunctionDeclarator) dtor).getParameters();
+ for (ICPPASTParameterDeclaration p : params)
+ guide.addParameterDeclaration(p);
+ guide.setVarArgs(((ICPPASTFunctionDeclarator) dtor).takesVarArgs());
+ IASTTypeId nameSpecifier = ((ICPPASTFunctionDeclarator) dtor).getTrailingReturnType();
+ IASTDeclSpecifier guideDeclSpec = nameSpecifier.getDeclSpecifier();
+ if (guideDeclSpec instanceof ICPPASTNamedTypeSpecifier) {
+ IASTName n = ((ICPPASTNamedTypeSpecifier) guideDeclSpec).getName();
+ if (n instanceof ICPPASTTemplateId) {
+ guide.setSimpleTemplateId((ICPPASTTemplateId) n);
+ } else {
+ throwBacktrack(dtor);
+ }
+ } else {
+ throwBacktrack(dtor);
+ }
+ setRange(guide, firstOffset, endOffset);
+ return guide;
+ }
+ }
+
// no function body
final boolean isAmbiguous = altDeclSpec != null && altDtor != null && declarators.length == 1;
@@ -3983,6 +4013,20 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
}
}
+ //Check if it's a possible C++17 deduction guide
+ if (dtor instanceof ICPPASTFunctionDeclarator) {
+ ICPPASTFunctionDeclarator possibleGuide = (ICPPASTFunctionDeclarator) dtor;
+ IASTTypeId returnType = possibleGuide.getTrailingReturnType();
+ if (returnType != null) {
+ IASTDeclSpecifier declSpec = returnType.getDeclSpecifier();
+ if (declSpec instanceof ICPPASTNamedTypeSpecifier) {
+ IASTName n = ((ICPPASTNamedTypeSpecifier) declSpec).getName();
+ if (n instanceof ICPPASTTemplateId)
+ return;
+ }
+ }
+ }
+
ASTNode node = (ASTNode) dtor;
throwBacktrack(node.getOffset(), node.getLength());
}
@@ -4755,44 +4799,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
int endOffset = last.getEndOffset();
final ICPPASTFunctionDeclarator fc = getNodeFactory().newFunctionDeclarator(null);
- ICPPASTParameterDeclaration pd = null;
- paramLoop: while (true) {
- switch (LT(1)) {
- case IToken.tRPAREN:
- case IToken.tEOC:
- endOffset = consume().getEndOffset();
- break paramLoop;
- case IToken.tELLIPSIS:
- consume();
- endOffset = consume(IToken.tRPAREN).getEndOffset();
- fc.setVarArgs(true);
- break paramLoop;
- case IToken.tCOMMA:
- if (pd == null)
- throwBacktrack(LA(1));
- endOffset = consume().getEndOffset();
- pd = null;
- break;
- default:
- if (pd != null)
- throwBacktrack(startOffset, endOffset - startOffset);
-
- pd = parameterDeclaration();
- fc.addParameterDeclaration(pd);
- endOffset = calculateEndOffset(pd);
- break;
- }
- }
- // Handle ambiguity between parameter pack and varargs.
- if (pd != null) {
- ICPPASTDeclarator dtor = pd.getDeclarator();
- if (dtor != null && !(dtor instanceof IASTAmbiguousDeclarator)) {
- if (dtor.declaresParameterPack() && dtor.getNestedDeclarator() == null && dtor.getInitializer() == null
- && dtor.getName().getSimpleID().length == 0) {
- ((IASTAmbiguityParent) fc).replace(pd, new CPPASTAmbiguousParameterDeclaration(pd));
- }
- }
- }
+ endOffset = parameterList(startOffset, endOffset, fc);
// Consume any number of __attribute__ tokens after the parameters
List+ * FORMATTER / Option to insert a space after deduction guide arrow + * - option id: "org.eclipse.cdt.core.formatter.insert_space_after_deduction_guide_arrow" + * - possible values: { INSERT, DO_NOT_INSERT } + * - default: INSERT + *+ * @see CCorePlugin#INSERT + * @see CCorePlugin#DO_NOT_INSERT + * @since 6.11 + */ + public static final String FORMATTER_INSERT_SPACE_AFTER_DEDUCTION_GUIDE_ARROW = CCorePlugin.PLUGIN_ID + + ".formatter.insert_space_after_deduction_guide_arrow"; //$NON-NLS-1$ + /** + *
+ * FORMATTER / Option to insert a space before deduction guide arrow + * - option id: "org.eclipse.cdt.core.formatter.insert_space_before_deduction_guide_arrow" + * - possible values: { INSERT, DO_NOT_INSERT } + * - default: INSERT + *+ * @see CCorePlugin#INSERT + * @see CCorePlugin#DO_NOT_INSERT + * @since 6.11 + */ + public static final String FORMATTER_INSERT_SPACE_BEFORE_DEDUCTION_GUIDE_ARROW = CCorePlugin.PLUGIN_ID + + ".formatter.insert_space_before_deduction_guide_arrow"; //$NON-NLS-1$ /** *
* FORMATTER / Option to insert a space before an assignment operator diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/DefaultCodeFormatterOptions.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/DefaultCodeFormatterOptions.java index dc6868739f5..6d8782c285c 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/DefaultCodeFormatterOptions.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/DefaultCodeFormatterOptions.java @@ -224,6 +224,14 @@ public class DefaultCodeFormatterOptions { * @since 6.8 */ public boolean insert_space_before_lambda_return; + /** + * @since 6.11 + */ + public boolean insert_space_after_deduction_guide_arrow; + /** + * @since 6.11 + */ + public boolean insert_space_before_deduction_guide_arrow; public boolean insert_space_before_assignment_operator; public boolean insert_space_before_binary_operator; public boolean insert_space_before_closing_angle_bracket_in_template_arguments; @@ -630,6 +638,10 @@ public class DefaultCodeFormatterOptions { this.insert_space_after_lambda_return ? CCorePlugin.INSERT : CCorePlugin.DO_NOT_INSERT); options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_LAMBDA_RETURN, this.insert_space_before_lambda_return ? CCorePlugin.INSERT : CCorePlugin.DO_NOT_INSERT); + options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_DEDUCTION_GUIDE_ARROW, + this.insert_space_after_deduction_guide_arrow ? CCorePlugin.INSERT : CCorePlugin.DO_NOT_INSERT); + options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_DEDUCTION_GUIDE_ARROW, + this.insert_space_before_deduction_guide_arrow ? CCorePlugin.INSERT : CCorePlugin.DO_NOT_INSERT); options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_ASSIGNMENT_OPERATOR, this.insert_space_before_assignment_operator ? CCorePlugin.INSERT : CCorePlugin.DO_NOT_INSERT); options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BINARY_OPERATOR, @@ -1756,6 +1768,18 @@ public class DefaultCodeFormatterOptions { if (insertSpaceBeforeLambdaReturnOption != null) { this.insert_space_before_lambda_return = CCorePlugin.INSERT.equals(insertSpaceBeforeLambdaReturnOption); } + final Object insertSpaceAfterDeductionGuideOption = settings + .get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_DEDUCTION_GUIDE_ARROW); + if (insertSpaceAfterDeductionGuideOption != null) { + this.insert_space_after_deduction_guide_arrow = CCorePlugin.INSERT + .equals(insertSpaceAfterDeductionGuideOption); + } + final Object insertSpaceBeforeDeductionGuideOption = settings + .get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_DEDUCTION_GUIDE_ARROW); + if (insertSpaceBeforeDeductionGuideOption != null) { + this.insert_space_before_deduction_guide_arrow = CCorePlugin.INSERT + .equals(insertSpaceBeforeDeductionGuideOption); + } final Object insertSpaceBeforeAssignmentOperatorOption = settings .get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_ASSIGNMENT_OPERATOR); if (insertSpaceBeforeAssignmentOperatorOption != null) { @@ -2438,6 +2462,8 @@ public class DefaultCodeFormatterOptions { this.insert_space_after_unary_operator = false; this.insert_space_after_lambda_return = true; this.insert_space_before_lambda_return = true; + this.insert_space_after_deduction_guide_arrow = true; + this.insert_space_before_deduction_guide_arrow = true; this.insert_space_before_assignment_operator = true; this.insert_space_before_binary_operator = true; this.insert_space_before_closing_angle_bracket_in_template_arguments = false; diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java index 2e3ce60c7a8..70fbedd4890 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/formatter/CodeFormatterVisitor.java @@ -122,6 +122,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorChainInitializer; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDecltypeSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeductionGuide; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeleteExpression; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDesignatedInitializer; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDesignator; @@ -724,6 +725,8 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, return visit((IASTFunctionDefinition) node); } else if (node instanceof IASTSimpleDeclaration) { return visit((IASTSimpleDeclaration) node); + } else if (node instanceof ICPPASTDeductionGuide) { + return visit((ICPPASTDeductionGuide) node); } else if (node instanceof IASTASMDeclaration) { return visit((IASTASMDeclaration) node); } else if (node instanceof ICPPASTVisibilityLabel) { @@ -1987,6 +1990,26 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor, return PROCESS_SKIP; } + private int visit(ICPPASTDeductionGuide node) { + node.getTemplateName().accept(this); + final Listparameters = Arrays.asList(node.getParameters()); + Runnable tailFormatter = new TrailingSemicolonFormatter(node); + final ListOptions options = new ListOptions(preferences.alignment_for_declarator_list); + options.fSpaceAfterSeparator = preferences.insert_space_after_comma_in_declarator_list; + options.fSpaceBeforeSeparator = preferences.insert_space_before_comma_in_declarator_list; + formatList(parameters, options, true, false, null); + + if (peekNextToken() == Token.tARROW) { + scribe.printNextToken(Token.tARROW, preferences.insert_space_before_deduction_guide_arrow); + if (preferences.insert_space_after_deduction_guide_arrow) { + scribe.space(); + } + } + node.getSimpleTemplateId().accept(this); + tailFormatter.run(); + return PROCESS_SKIP; + } + private int visit(IASTSimpleDeclaration node) { if (node instanceof ICPPASTStructuredBindingDeclaration) { return visit((ICPPASTStructuredBindingDeclaration) node); diff --git a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java index 88a6229a737..74997c84ac7 100644 --- a/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java +++ b/core/org.eclipse.cdt.ui.tests/ui/org/eclipse/cdt/ui/tests/text/CodeFormatterTest.java @@ -4734,4 +4734,41 @@ public class CodeFormatterTest extends BaseUITestCase { public void testFormatterOnOff_Bug559669() throws Exception { assertFormatterResult(); } + + //template + //struct U; + //U()->U ; + + //template + //struct U; + //U() -> U ; + public void testDeductionGuide() throws Exception { + assertFormatterResult(); + } + + //template + //struct U; + //template + //U(C)->U ; + + //template + //struct U; + //template + //U(C) -> U ; + public void testDeductionGuideTemplate() throws Exception { + assertFormatterResult(); + } + + //template + //struct U; + //template + //explicit U(C)->U ; + + //template + //struct U; + //template + //explicit U(C) -> U ; + public void testDeductionGuideExplicit() throws Exception { + assertFormatterResult(); + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/FormatterMessages.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/FormatterMessages.java index 7deb8d1086b..82737ec5982 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/FormatterMessages.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/FormatterMessages.java @@ -212,6 +212,10 @@ final class FormatterMessages extends NLS { public static String WhiteSpaceOptions_structured_binding_before_comma_in_name_list; public static String WhiteSpaceOptions_structured_binding_after_comma_in_name_list; public static String WhiteSpaceOptions_structured_binding_before_name_list_closing_bracket; + public static String WhiteSpaceTabPage_deduction_guide_declarations; + public static String WhiteSpaceTabPage_deduction_guide_before_arrow; + public static String WhiteSpaceTabPage_deduction_guide_after_arrow; + public static String WhiteSpaceOptions_deduction_guide_arrow_operator; // public static String WhiteSpaceOptions_before_ellipsis; // public static String WhiteSpaceOptions_after_ellipsis; // public static String WhiteSpaceOptions_return_with_parenthesized_expression; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/FormatterMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/FormatterMessages.properties index 6921dc869ed..94d45b8107f 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/FormatterMessages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/FormatterMessages.properties @@ -34,6 +34,10 @@ WhiteSpaceTabPage_lambda_expressions=Lambda expressions WhiteSpaceTabPage_lambda_before_return=before return arrow WhiteSpaceTabPage_lambda_after_return=after return arrow +WhiteSpaceTabPage_deduction_guide_declarations=Deduction guide +WhiteSpaceTabPage_deduction_guide_before_arrow=before arrow +WhiteSpaceTabPage_deduction_guide_after_arrow=after arrow + WhiteSpaceTabPage_classes=Types WhiteSpaceTabPage_classes_before_opening_brace_of_a_class=before opening brace of a class WhiteSpaceTabPage_classes_before_colon_of_base_clause=before colon of base clause @@ -146,6 +150,7 @@ WhiteSpaceOptions_unary_operator=Unary operator WhiteSpaceOptions_prefix_operator=Prefix operator WhiteSpaceOptions_postfix_operator=Postfix operator WhiteSpaceOptions_lambda_arrow_operator=Lambda arrow operator +WhiteSpaceOptions_deduction_guide_arrow_operator=Deduction guide arrow operator WhiteSpaceOptions_pointer=Pointer WhiteSpaceOptions_before_pointer=Before pointer diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/WhiteSpaceOptions.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/WhiteSpaceOptions.java index 95e938b5ff6..78116c21743 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/WhiteSpaceOptions.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/preferences/formatter/WhiteSpaceOptions.java @@ -183,6 +183,9 @@ public final class WhiteSpaceOptions { private final PreviewSnippet LAMBDA_PREVIEW = new PreviewSnippet(CodeFormatter.K_CLASS_BODY_DECLARATIONS, "void foo() { auto f = []()->int{return 0;};}"); //$NON-NLS-1$ + private final PreviewSnippet DEDUCTION_GUIDE_PREVIEW = new PreviewSnippet(CodeFormatter.K_CLASS_BODY_DECLARATIONS, + "template struct U;\ntemplate \nU(C) -> U ;"); //$NON-NLS-1$ + private final PreviewSnippet INITIALIZER_LIST_PREVIEW = new PreviewSnippet(CodeFormatter.K_STATEMENTS, "int array[]= {1, 2, 3};"); //$NON-NLS-1$ @@ -478,6 +481,7 @@ public final class WhiteSpaceOptions { createLinkageTree(workingValues, declarations); // createConstructorTree(workingValues, declarations); createLambdaDeclTree(workingValues, declarations); + createDeductionDeclTree(workingValues, declarations); createMethodDeclTree(workingValues, declarations); createExceptionSpecificationTree(workingValues, declarations); createLabelTree(workingValues, declarations); @@ -606,6 +610,9 @@ public final class WhiteSpaceOptions { DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_POSTFIX_OPERATOR, OPERATOR_PREVIEW); createOption(parent, workingValues, FormatterMessages.WhiteSpaceOptions_lambda_arrow_operator, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_LAMBDA_RETURN, LAMBDA_PREVIEW); + createOption(parent, workingValues, FormatterMessages.WhiteSpaceOptions_deduction_guide_arrow_operator, + DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_DEDUCTION_GUIDE_ARROW, + DEDUCTION_GUIDE_PREVIEW); } private void createBeforeClosingBracketTree(Map workingValues, final InnerNode parent) { @@ -852,6 +859,9 @@ public final class WhiteSpaceOptions { DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_POSTFIX_OPERATOR, OPERATOR_PREVIEW); createOption(parent, workingValues, FormatterMessages.WhiteSpaceOptions_lambda_arrow_operator, DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_LAMBDA_RETURN, LAMBDA_PREVIEW); + createOption(parent, workingValues, FormatterMessages.WhiteSpaceOptions_deduction_guide_arrow_operator, + DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_DEDUCTION_GUIDE_ARROW, + DEDUCTION_GUIDE_PREVIEW); } private void createAfterOpenBracketTree(Map workingValues, final InnerNode parent) { @@ -1004,6 +1014,19 @@ public final class WhiteSpaceOptions { return root; } + private InnerNode createDeductionDeclTree(Map workingValues, InnerNode parent) { + final InnerNode root = new InnerNode(parent, workingValues, + FormatterMessages.WhiteSpaceTabPage_deduction_guide_declarations); + + createOption(root, workingValues, FormatterMessages.WhiteSpaceTabPage_deduction_guide_before_arrow, + DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_DEDUCTION_GUIDE_ARROW, + DEDUCTION_GUIDE_PREVIEW); + createOption(root, workingValues, FormatterMessages.WhiteSpaceTabPage_deduction_guide_after_arrow, + DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_DEDUCTION_GUIDE_ARROW, + DEDUCTION_GUIDE_PREVIEW); + return root; + } + private InnerNode createLambdaDeclTree(Map workingValues, InnerNode parent) { final InnerNode root = new InnerNode(parent, workingValues, FormatterMessages.WhiteSpaceTabPage_lambda_expressions);