diff options
Diffstat (limited to 'core')
18 files changed, 760 insertions, 41 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 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<typename> struct U; + // U() -> U<int>; + public void testDeductionGuideWithoutArguments() throws Exception { + IASTDeclaration[] declarations = parseAndCheckBindings().getDeclarations(); + + ICPPASTDeductionGuide guide = firstGuide(declarations); + MatcherAssert.assertThat(guide.getParameters(), is(arrayWithSize(0))); + MatcherAssert.assertThat(guide.getTemplateName(), hasToString("U")); + MatcherAssert.assertThat(guide.getSimpleTemplateId().getTemplateName(), hasToString("U")); + MatcherAssert.assertThat(guide.isExplicit(), is(equalTo(false))); + } + + // template<typename> struct U; + // U(int, float) -> U<int>; + public void testDeductionGuideWithArguments() throws Exception { + IASTDeclaration[] declarations = parseAndCheckBindings().getDeclarations(); + + ICPPASTDeductionGuide guide = firstGuide(declarations); + MatcherAssert.assertThat(guide.getParameters(), is(arrayWithSize(2))); + MatcherAssert.assertThat(guide.getTemplateName(), hasToString("U")); + MatcherAssert.assertThat(guide.getSimpleTemplateId().getTemplateName(), hasToString("U")); + MatcherAssert.assertThat(guide.isExplicit(), is(equalTo(false))); + } + + // template<typename> struct U; + // template<typename T> + // U(T) -> U<T>; + public void testDeductionGuideTemplate() throws Exception { + IASTDeclaration[] declarations = parseAndCheckBindings().getDeclarations(); + ICPPASTTemplateDeclaration template = (ICPPASTTemplateDeclaration) declarations[1]; + ICPPASTDeductionGuide guide = (ICPPASTDeductionGuide) template.getDeclaration(); + + MatcherAssert.assertThat(guide.getParameters(), is(arrayWithSize(1))); + MatcherAssert.assertThat(guide.getTemplateName(), hasToString("U")); + MatcherAssert.assertThat(guide.getSimpleTemplateId().getTemplateName(), hasToString("U")); + MatcherAssert.assertThat(guide.isExplicit(), is(equalTo(false))); + } + + // template<typename> struct U; + // explicit U() -> U<int>; + public void testExplicitDeductionGuide() throws Exception { + IASTDeclaration[] declarations = parseAndCheckBindings().getDeclarations(); + + ICPPASTDeductionGuide guide = firstGuide(declarations); + MatcherAssert.assertThat(guide.getParameters(), is(arrayWithSize(0))); + MatcherAssert.assertThat(guide.getTemplateName(), hasToString("U")); + MatcherAssert.assertThat(guide.getSimpleTemplateId().getTemplateName(), hasToString("U")); + MatcherAssert.assertThat(guide.isExplicit(), is(equalTo(true))); + } + + // template<typename> struct U; + // template<typename T> + // explicit U(T) -> U<T>; + public void testExplicitDeductionGuideTemplate() throws Exception { + IASTDeclaration[] declarations = parseAndCheckBindings().getDeclarations(); + ICPPASTTemplateDeclaration template = (ICPPASTTemplateDeclaration) declarations[1]; + ICPPASTDeductionGuide guide = (ICPPASTDeductionGuide) template.getDeclaration(); + + MatcherAssert.assertThat(guide.getParameters(), is(arrayWithSize(1))); + MatcherAssert.assertThat(guide.getTemplateName(), hasToString("U")); + MatcherAssert.assertThat(guide.getSimpleTemplateId().getTemplateName(), hasToString("U")); + MatcherAssert.assertThat(guide.isExplicit(), is(equalTo(true))); + } + + // struct S { + // template<typename> struct U; + // U() -> U<int>; + // }; + public void testDeductionGuideWithoutArgumentsForNestedClassType() throws Exception { + IASTTranslationUnit tu = parseAndCheckBindings(); + IASTSimpleDeclaration declaration = (IASTSimpleDeclaration) tu.getDeclarations()[0]; + ICPPASTCompositeTypeSpecifier struct = (ICPPASTCompositeTypeSpecifier) declaration.getDeclSpecifier(); + IASTDeclaration[] members = struct.getMembers(); + + ICPPASTDeductionGuide guide = firstGuide(members); + MatcherAssert.assertThat(guide.getParameters(), is(arrayWithSize(0))); + MatcherAssert.assertThat(guide.getTemplateName(), hasToString("U")); + MatcherAssert.assertThat(guide.getSimpleTemplateId().getTemplateName(), hasToString("U")); + MatcherAssert.assertThat(guide.isExplicit(), is(equalTo(false))); + } + + // struct S { + // template<typename> struct U; + // U(char, bool) -> U<double>; + // }; + public void testDeductionGuideWithArgumentsForNestedClassType() throws Exception { + IASTTranslationUnit tu = parseAndCheckBindings(); + IASTSimpleDeclaration declaration = (IASTSimpleDeclaration) tu.getDeclarations()[0]; + ICPPASTCompositeTypeSpecifier struct = (ICPPASTCompositeTypeSpecifier) declaration.getDeclSpecifier(); + IASTDeclaration[] members = struct.getMembers(); + + ICPPASTDeductionGuide guide = firstGuide(members); + MatcherAssert.assertThat(guide.getParameters(), is(arrayWithSize(2))); + MatcherAssert.assertThat(guide.getTemplateName(), hasToString("U")); + MatcherAssert.assertThat(guide.getSimpleTemplateId().getTemplateName(), hasToString("U")); + MatcherAssert.assertThat(guide.isExplicit(), is(equalTo(false))); + } + + // struct S { + // template<typename> struct U; + // template<typename T> + // U(T) -> U<T>; + // }; + public void testDeductionGuideTemplateWithArgumentsForNestedClassType() throws Exception { + IASTTranslationUnit tu = parseAndCheckBindings(); + IASTSimpleDeclaration declaration = (IASTSimpleDeclaration) tu.getDeclarations()[0]; + ICPPASTCompositeTypeSpecifier struct = (ICPPASTCompositeTypeSpecifier) declaration.getDeclSpecifier(); + IASTDeclaration[] members = struct.getMembers(); + ICPPASTTemplateDeclaration template = (ICPPASTTemplateDeclaration) members[1]; + + ICPPASTDeductionGuide guide = (ICPPASTDeductionGuide) template.getDeclaration(); + MatcherAssert.assertThat(guide.getParameters(), is(arrayWithSize(1))); + MatcherAssert.assertThat(guide.getTemplateName(), hasToString("U")); + MatcherAssert.assertThat(guide.getSimpleTemplateId().getTemplateName(), hasToString("U")); + MatcherAssert.assertThat(guide.isExplicit(), is(equalTo(false))); + } + + // struct S { + // template<typename> struct U; + // explicit U() -> U<int>; + // }; + public void testExplicitDeductionGuideForNestedClassType() throws Exception { + IASTTranslationUnit tu = parseAndCheckBindings(); + IASTSimpleDeclaration declaration = (IASTSimpleDeclaration) tu.getDeclarations()[0]; + ICPPASTCompositeTypeSpecifier struct = (ICPPASTCompositeTypeSpecifier) declaration.getDeclSpecifier(); + IASTDeclaration[] members = struct.getMembers(); + + ICPPASTDeductionGuide guide = firstGuide(members); + MatcherAssert.assertThat(guide.getParameters(), is(arrayWithSize(0))); + MatcherAssert.assertThat(guide.getTemplateName(), hasToString("U")); + MatcherAssert.assertThat(guide.getSimpleTemplateId().getTemplateName(), hasToString("U")); + MatcherAssert.assertThat(guide.isExplicit(), is(equalTo(true))); + } + + // struct S { + // template<typename> struct U; + // template<typename T> + // explicit U(T) -> U<T>; + // }; + public void testExplicitDeductionGuideTemplateForNestedClassType() throws Exception { + IASTTranslationUnit tu = parseAndCheckBindings(); + IASTSimpleDeclaration declaration = (IASTSimpleDeclaration) tu.getDeclarations()[0]; + ICPPASTCompositeTypeSpecifier struct = (ICPPASTCompositeTypeSpecifier) declaration.getDeclSpecifier(); + IASTDeclaration[] members = struct.getMembers(); + ICPPASTTemplateDeclaration template = (ICPPASTTemplateDeclaration) members[1]; + + ICPPASTDeductionGuide guide = (ICPPASTDeductionGuide) template.getDeclaration(); + MatcherAssert.assertThat(guide.getParameters(), is(arrayWithSize(1))); + MatcherAssert.assertThat(guide.getTemplateName(), hasToString("U")); + MatcherAssert.assertThat(guide.getSimpleTemplateId().getTemplateName(), hasToString("U")); + MatcherAssert.assertThat(guide.isExplicit(), is(equalTo(true))); + } +} diff --git a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelBuilder2.java b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelBuilder2.java index 63c983b1b11..4364123abb1 100644 --- a/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelBuilder2.java +++ b/core/org.eclipse.cdt.core/model/org/eclipse/cdt/internal/core/model/CModelBuilder2.java @@ -55,6 +55,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTAliasDeclaration; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeductionGuide; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; @@ -352,6 +353,8 @@ public class CModelBuilder2 implements IContributedModelBuilder { // TODO [cmodel] problem declaration? } else if (declaration instanceof ICPPASTStaticAssertDeclaration) { // ignore + } else if (declaration instanceof ICPPASTDeductionGuide) { + // TODO [cmodel] deduction guide? } else { assert false : "TODO: " + declaration.getClass().getName(); //$NON-NLS-1$ } @@ -416,6 +419,8 @@ public class CModelBuilder2 implements IContributedModelBuilder { createTemplateDeclaration(parent, (ICPPASTTemplateDeclaration) declaration); } else if (declaration instanceof IASTProblemDeclaration) { // ignore problem declarations (or create special elements for debugging?) + } else if (declaration instanceof ICPPASTDeductionGuide) { + // TODO [cmodel] deduction guide? } else { assert false : "TODO: " + declaration.getClass().getName(); //$NON-NLS-1$ } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTDeductionGuide.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTDeductionGuide.java new file mode 100644 index 00000000000..0d455df90c5 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/cpp/ICPPASTDeductionGuide.java @@ -0,0 +1,99 @@ +/******************************************************************************* + * Copyright (c) 2018, Institute for Software and others. + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Felix Morgner - 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; +import org.eclipse.cdt.core.dom.ast.IASTName; + +/** + * A C++ class-template argument deduction guide + * <p> + * e.g: + * + * <pre> + * SomeTemplateName(int) -> SomeTemplateName<float>; + * + * template<typename I> + * SomeTemplateName(I, I) -> SomeTemplateName<typename std::iterator_traits<I>::value_type>; + * </pre> + * </p> + * + * @noimplement This interface is not intended to be implemented by clients. + * @noextend This interface is not intended to be extended by clients. + * @since 6.11 + */ +public interface ICPPASTDeductionGuide extends IASTDeclaration, ICPPASTParameterListOwner { + + /** + * <code>TEMPLATE_NAME</code> represents the relationship between an + * <code>ICPPASTDeductionGuide</code> and it's nested + * <code>IASTName</code>. + */ + static final ASTNodeProperty TEMPLATE_NAME = new ASTNodeProperty( + "ICPPASTDeductionGuide.TEMPLATE_NAME - IASTName for ICPPASTDeductionGuide"); //$NON-NLS-1$ + + /** + * <code>TEMPLATE_ID</code> represents the relationship between an + * <code>ICPPASTDeductionGuide</code> and it's nested + * <code>ICPPASTTemplateId</code>. + */ + static final ASTNodeProperty TEMPLATE_ID = new ASTNodeProperty( + "ICPPASTDeductionGuide.TEMPLATE_ID - ICPPASTTemplateId for ICPPASTDeductionGuide"); //$NON-NLS-1$ + + /** + * <code>PARAMETER</code> represents the relationship between an + * <code>ICPPASTDeductionGuide</code> and it's nested + * <code>IASTParameterDeclaration</code>. + */ + 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<IASTAttributeSpecifier> attributes = __attribute_decl_seq(supportAttributeSpecifiers, false); @@ -4898,6 +4905,58 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser { } /** + * Parse a paramter list + * @param start Start offset + * @param end End offset + * @param owner The list owner + * @return The end offset after parsing + * @throws EndOfFileException + * @throws BacktrackException + */ + private int parameterList(int start, int end, ICPPASTParameterListOwner owner) + throws EndOfFileException, BacktrackException { + ICPPASTParameterDeclaration pd = null; + paramLoop: while (true) { + switch (LT(1)) { + case IToken.tRPAREN: + case IToken.tEOC: + end = consume().getEndOffset(); + break paramLoop; + case IToken.tELLIPSIS: + consume(); + end = consume(IToken.tRPAREN).getEndOffset(); + owner.setVarArgs(true); + break paramLoop; + case IToken.tCOMMA: + if (pd == null) + throwBacktrack(LA(1)); + end = consume().getEndOffset(); + pd = null; + break; + default: + if (pd != null) + throwBacktrack(start, end - start); + + pd = parameterDeclaration(); + owner.addParameterDeclaration(pd); + end = 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) owner).replace(pd, new CPPASTAmbiguousParameterDeclaration(pd)); + } + } + } + return end; + } + + /** * Parse an array declarator starting at the square bracket. */ private ICPPASTArrayDeclarator arrayDeclarator(DeclarationOptions option) 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 11cc4769f92..813e5a568c6 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 @@ -117,6 +117,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConstructorInitializer; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTConversionName; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclarator; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeductionGuide; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTEnumerationSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation; @@ -859,6 +860,9 @@ public class CPPVisitor extends ASTQueries { return null; } else if (parent instanceof ICPPASTTemplateDeclaration) { return CPPTemplates.createBinding(param); + } else if (parent instanceof ICPPASTDeductionGuide) { + ICPPASTDeductionGuide guide = (ICPPASTDeductionGuide) parent; + return new CPPParameter(name, findParameterIndex(param, guide.getParameters())); } return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_TYPE); } diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/DefaultCodeFormatterConstants.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/DefaultCodeFormatterConstants.java index 0c2e2d6e25e..274995ba64c 100644 --- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/DefaultCodeFormatterConstants.java +++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/formatter/DefaultCodeFormatterConstants.java @@ -1624,6 +1624,32 @@ public class DefaultCodeFormatterConstants { + ".formatter.insert_space_before_lambda_return"; //$NON-NLS-1$ /** * <pre> + * 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 + * </pre> + * @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$ + /** + * <pre> + * 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 + * </pre> + * @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$ + /** + * <pre> * FORMATTER / Option to insert a space before an assignment operator * - option id: "org.eclipse.cdt.core.formatter.insert_space_before_assignment_operator" * - possible values: { INSERT, DO_NOT_INSERT } 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 List<IASTParameterDeclaration> parameters = 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<class T> + //struct U; + //U()->U<int>; + + //template<class T> + //struct U; + //U() -> U<int>; + public void testDeductionGuide() throws Exception { + assertFormatterResult(); + } + + //template<class T> + //struct U; + //template<class C> + //U(C)->U<C>; + + //template<class T> + //struct U; + //template<class C> + //U(C) -> U<C>; + public void testDeductionGuideTemplate() throws Exception { + assertFormatterResult(); + } + + //template<class T> + //struct U; + //template<class C> + //explicit U(C)->U<C>; + + //template<class T> + //struct U; + //template<class C> + //explicit U(C) -> U<C>; + 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<typename T> struct U;\ntemplate<typename C>\nU(C) -> U<C>;"); //$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<String, String> 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<String, String> workingValues, final InnerNode parent) { @@ -1004,6 +1014,19 @@ public final class WhiteSpaceOptions { return root; } + private InnerNode createDeductionDeclTree(Map<String, String> 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<String, String> workingValues, InnerNode parent) { final InnerNode root = new InnerNode(parent, workingValues, FormatterMessages.WhiteSpaceTabPage_lambda_expressions); |