1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-22 14:12:10 +02:00

541239: [C++17] Implement parser support for deduction guides

Change-Id: I1683583af981d276b346ba8470a9044cfd8921cd
Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=541239
Signed-off-by: Felix Morgner <fmorgner@hsr.ch>
Also-by: Marco Stornelli <marco.stornelli@gmail.com>
This commit is contained in:
Felix Morgner 2018-11-14 10:26:59 +01:00 committed by Marco Stornelli
parent 5823d56a2d
commit bcb955a321
18 changed files with 760 additions and 41 deletions

View file

@ -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.InitCaptureTests;
import org.eclipse.cdt.core.parser.tests.ast2.cxx14.ReturnTypeDeductionTests; 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.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.LambdaExpressionTests;
import org.eclipse.cdt.core.parser.tests.ast2.cxx17.StructuredBindingTests; import org.eclipse.cdt.core.parser.tests.ast2.cxx17.StructuredBindingTests;
import org.eclipse.cdt.core.parser.tests.ast2.cxx17.TemplateAutoTests; import org.eclipse.cdt.core.parser.tests.ast2.cxx17.TemplateAutoTests;
@ -76,6 +77,7 @@ public class DOMParserTestSuite extends TestCase {
suite.addTest(TemplateAutoTests.suite()); suite.addTest(TemplateAutoTests.suite());
suite.addTestSuite(LambdaExpressionTests.class); suite.addTestSuite(LambdaExpressionTests.class);
suite.addTestSuite(StructuredBindingTests.class); suite.addTestSuite(StructuredBindingTests.class);
suite.addTestSuite(DeductionGuideTests.class);
return suite; return suite;
} }
} }

View file

@ -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)));
}
}

View file

@ -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;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; 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.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.ICPPASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTFunctionDeclarator;
@ -352,6 +353,8 @@ public class CModelBuilder2 implements IContributedModelBuilder {
// TODO [cmodel] problem declaration? // TODO [cmodel] problem declaration?
} else if (declaration instanceof ICPPASTStaticAssertDeclaration) { } else if (declaration instanceof ICPPASTStaticAssertDeclaration) {
// ignore // ignore
} else if (declaration instanceof ICPPASTDeductionGuide) {
// TODO [cmodel] deduction guide?
} else { } else {
assert false : "TODO: " + declaration.getClass().getName(); //$NON-NLS-1$ assert false : "TODO: " + declaration.getClass().getName(); //$NON-NLS-1$
} }
@ -416,6 +419,8 @@ public class CModelBuilder2 implements IContributedModelBuilder {
createTemplateDeclaration(parent, (ICPPASTTemplateDeclaration) declaration); createTemplateDeclaration(parent, (ICPPASTTemplateDeclaration) declaration);
} else if (declaration instanceof IASTProblemDeclaration) { } else if (declaration instanceof IASTProblemDeclaration) {
// ignore problem declarations (or create special elements for debugging?) // ignore problem declarations (or create special elements for debugging?)
} else if (declaration instanceof ICPPASTDeductionGuide) {
// TODO [cmodel] deduction guide?
} else { } else {
assert false : "TODO: " + declaration.getClass().getName(); //$NON-NLS-1$ assert false : "TODO: " + declaration.getClass().getName(); //$NON-NLS-1$
} }

View file

@ -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&lt;float&gt;;
*
* template&lt;typename I&gt;
* SomeTemplateName(I, I) -> SomeTemplateName&lt;typename std::iterator_traits&lt;I&gt;::value_type&gt;;
* </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);
}

View file

@ -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. * @noimplement This interface is not intended to be implemented by clients.
* @noextend This interface is not intended to be extended 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 * @since 5.9
*/ */

View file

@ -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();
}

View file

@ -34,14 +34,15 @@ public class DeclarationOptions {
final public static int SINGLE_DTOR = 0x4000; final public static int SINGLE_DTOR = 0x4000;
final public static int ALLOW_FUNCTION_DEFINITION = 0x8000; final public static int ALLOW_FUNCTION_DEFINITION = 0x8000;
final public static int NO_COMPOSITE_SPECIFIER = 0x10000; final public static int NO_COMPOSITE_SPECIFIER = 0x10000;
final public static int ALLOW_DEDUCTION_GUIDE = 0x20000;
public static final DeclarationOptions GLOBAL = new DeclarationOptions( 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( FUNCTION_STYLE_ASM = new DeclarationOptions(
ALLOW_EMPTY_SPECIFIER | NO_INITIALIZER | ALLOW_ABSTRACT | ALLOW_FUNCTION_DEFINITION), ALLOW_EMPTY_SPECIFIER | NO_INITIALIZER | ALLOW_ABSTRACT | ALLOW_FUNCTION_DEFINITION),
C_MEMBER = new DeclarationOptions(ALLOW_BITFIELD | ALLOW_ABSTRACT), C_MEMBER = new DeclarationOptions(ALLOW_BITFIELD | ALLOW_ABSTRACT),
CPP_MEMBER = new DeclarationOptions(ALLOW_EMPTY_SPECIFIER | ALLOW_BITFIELD | ALLOW_OPAQUE_ENUM 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), LOCAL = new DeclarationOptions(ALLOW_OPAQUE_ENUM),
PARAMETER = new DeclarationOptions(ALLOW_ABSTRACT | ALLOW_PARAMETER_PACKS | REQUIRE_SIMPLE_NAME PARAMETER = new DeclarationOptions(ALLOW_ABSTRACT | ALLOW_PARAMETER_PACKS | REQUIRE_SIMPLE_NAME
| NO_BRACED_INITIALIZER | NO_CTOR_STYLE_INITIALIZER), | NO_BRACED_INITIALIZER | NO_CTOR_STYLE_INITIALIZER),

View file

@ -47,6 +47,7 @@ public class CPPASTAmbiguousTemplateArgument extends ASTAmbiguousNode implements
fNodes = new ArrayList<>(2); fNodes = new ArrayList<>(2);
for (IASTNode node : nodes) { for (IASTNode node : nodes) {
if (node instanceof IASTTypeId || node instanceof IASTExpression) { if (node instanceof IASTTypeId || node instanceof IASTExpression) {
node.setParent(this);
fNodes.add(node); fNodes.add(node);
} else { } else {
Assert.isLegal(false, node == null ? "null" : node.getClass().getName()); //$NON-NLS-1$ Assert.isLegal(false, node == null ? "null" : node.getClass().getName()); //$NON-NLS-1$

View file

@ -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;
}
}
}

View file

@ -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.ICPPASTOperatorName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTPackExpandable; 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.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.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTRangeBasedForStatement; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTRangeBasedForStatement;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTReferenceOperator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTReferenceOperator;
@ -3055,6 +3056,35 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
throwBacktrack(LA(1)); 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 // no function body
final boolean isAmbiguous = altDeclSpec != null && altDtor != null && declarators.length == 1; 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; ASTNode node = (ASTNode) dtor;
throwBacktrack(node.getOffset(), node.getLength()); throwBacktrack(node.getOffset(), node.getLength());
} }
@ -4755,44 +4799,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
int endOffset = last.getEndOffset(); int endOffset = last.getEndOffset();
final ICPPASTFunctionDeclarator fc = getNodeFactory().newFunctionDeclarator(null); final ICPPASTFunctionDeclarator fc = getNodeFactory().newFunctionDeclarator(null);
ICPPASTParameterDeclaration pd = null; endOffset = parameterList(startOffset, endOffset, fc);
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));
}
}
}
// Consume any number of __attribute__ tokens after the parameters // Consume any number of __attribute__ tokens after the parameters
List<IASTAttributeSpecifier> attributes = __attribute_decl_seq(supportAttributeSpecifiers, false); List<IASTAttributeSpecifier> attributes = __attribute_decl_seq(supportAttributeSpecifiers, false);
@ -4897,6 +4904,58 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
return setRange(fc, startOffset, endOffset); return setRange(fc, startOffset, endOffset);
} }
/**
* 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. * Parse an array declarator starting at the square bracket.
*/ */

View file

@ -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.ICPPASTConversionName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; 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.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.ICPPASTElaboratedTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTEnumerationSpecifier; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTEnumerationSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTExplicitTemplateInstantiation;
@ -859,6 +860,9 @@ public class CPPVisitor extends ASTQueries {
return null; return null;
} else if (parent instanceof ICPPASTTemplateDeclaration) { } else if (parent instanceof ICPPASTTemplateDeclaration) {
return CPPTemplates.createBinding(param); 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); return new ProblemBinding(name, IProblemBinding.SEMANTIC_INVALID_TYPE);
} }

View file

@ -1622,6 +1622,32 @@ public class DefaultCodeFormatterConstants {
*/ */
public static final String FORMATTER_INSERT_SPACE_BEFORE_LAMBDA_RETURN = CCorePlugin.PLUGIN_ID public static final String FORMATTER_INSERT_SPACE_BEFORE_LAMBDA_RETURN = CCorePlugin.PLUGIN_ID
+ ".formatter.insert_space_before_lambda_return"; //$NON-NLS-1$ + ".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> * <pre>
* FORMATTER / Option to insert a space before an assignment operator * FORMATTER / Option to insert a space before an assignment operator

View file

@ -224,6 +224,14 @@ public class DefaultCodeFormatterOptions {
* @since 6.8 * @since 6.8
*/ */
public boolean insert_space_before_lambda_return; 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_assignment_operator;
public boolean insert_space_before_binary_operator; public boolean insert_space_before_binary_operator;
public boolean insert_space_before_closing_angle_bracket_in_template_arguments; 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); this.insert_space_after_lambda_return ? CCorePlugin.INSERT : CCorePlugin.DO_NOT_INSERT);
options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_LAMBDA_RETURN, options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_LAMBDA_RETURN,
this.insert_space_before_lambda_return ? CCorePlugin.INSERT : CCorePlugin.DO_NOT_INSERT); 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, options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_ASSIGNMENT_OPERATOR,
this.insert_space_before_assignment_operator ? CCorePlugin.INSERT : CCorePlugin.DO_NOT_INSERT); this.insert_space_before_assignment_operator ? CCorePlugin.INSERT : CCorePlugin.DO_NOT_INSERT);
options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BINARY_OPERATOR, options.put(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_BINARY_OPERATOR,
@ -1756,6 +1768,18 @@ public class DefaultCodeFormatterOptions {
if (insertSpaceBeforeLambdaReturnOption != null) { if (insertSpaceBeforeLambdaReturnOption != null) {
this.insert_space_before_lambda_return = CCorePlugin.INSERT.equals(insertSpaceBeforeLambdaReturnOption); 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 final Object insertSpaceBeforeAssignmentOperatorOption = settings
.get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_ASSIGNMENT_OPERATOR); .get(DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_ASSIGNMENT_OPERATOR);
if (insertSpaceBeforeAssignmentOperatorOption != null) { if (insertSpaceBeforeAssignmentOperatorOption != null) {
@ -2438,6 +2462,8 @@ public class DefaultCodeFormatterOptions {
this.insert_space_after_unary_operator = false; this.insert_space_after_unary_operator = false;
this.insert_space_after_lambda_return = true; this.insert_space_after_lambda_return = true;
this.insert_space_before_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_assignment_operator = true;
this.insert_space_before_binary_operator = true; this.insert_space_before_binary_operator = true;
this.insert_space_before_closing_angle_bracket_in_template_arguments = false; this.insert_space_before_closing_angle_bracket_in_template_arguments = false;

View file

@ -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.ICPPASTConstructorInitializer;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDeclSpecifier; 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.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.ICPPASTDeleteExpression;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDesignatedInitializer; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDesignatedInitializer;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDesignator; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTDesignator;
@ -724,6 +725,8 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
return visit((IASTFunctionDefinition) node); return visit((IASTFunctionDefinition) node);
} else if (node instanceof IASTSimpleDeclaration) { } else if (node instanceof IASTSimpleDeclaration) {
return visit((IASTSimpleDeclaration) node); return visit((IASTSimpleDeclaration) node);
} else if (node instanceof ICPPASTDeductionGuide) {
return visit((ICPPASTDeductionGuide) node);
} else if (node instanceof IASTASMDeclaration) { } else if (node instanceof IASTASMDeclaration) {
return visit((IASTASMDeclaration) node); return visit((IASTASMDeclaration) node);
} else if (node instanceof ICPPASTVisibilityLabel) { } else if (node instanceof ICPPASTVisibilityLabel) {
@ -1987,6 +1990,26 @@ public class CodeFormatterVisitor extends ASTVisitor implements ICPPASTVisitor,
return PROCESS_SKIP; 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) { private int visit(IASTSimpleDeclaration node) {
if (node instanceof ICPPASTStructuredBindingDeclaration) { if (node instanceof ICPPASTStructuredBindingDeclaration) {
return visit((ICPPASTStructuredBindingDeclaration) node); return visit((ICPPASTStructuredBindingDeclaration) node);

View file

@ -4734,4 +4734,41 @@ public class CodeFormatterTest extends BaseUITestCase {
public void testFormatterOnOff_Bug559669() throws Exception { public void testFormatterOnOff_Bug559669() throws Exception {
assertFormatterResult(); 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();
}
} }

View file

@ -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_before_comma_in_name_list;
public static String WhiteSpaceOptions_structured_binding_after_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 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_before_ellipsis;
// public static String WhiteSpaceOptions_after_ellipsis; // public static String WhiteSpaceOptions_after_ellipsis;
// public static String WhiteSpaceOptions_return_with_parenthesized_expression; // public static String WhiteSpaceOptions_return_with_parenthesized_expression;

View file

@ -34,6 +34,10 @@ WhiteSpaceTabPage_lambda_expressions=Lambda expressions
WhiteSpaceTabPage_lambda_before_return=before return arrow WhiteSpaceTabPage_lambda_before_return=before return arrow
WhiteSpaceTabPage_lambda_after_return=after 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=Types
WhiteSpaceTabPage_classes_before_opening_brace_of_a_class=before opening brace of a class 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 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_prefix_operator=Prefix operator
WhiteSpaceOptions_postfix_operator=Postfix operator WhiteSpaceOptions_postfix_operator=Postfix operator
WhiteSpaceOptions_lambda_arrow_operator=Lambda arrow operator WhiteSpaceOptions_lambda_arrow_operator=Lambda arrow operator
WhiteSpaceOptions_deduction_guide_arrow_operator=Deduction guide arrow operator
WhiteSpaceOptions_pointer=Pointer WhiteSpaceOptions_pointer=Pointer
WhiteSpaceOptions_before_pointer=Before pointer WhiteSpaceOptions_before_pointer=Before pointer

View file

@ -183,6 +183,9 @@ public final class WhiteSpaceOptions {
private final PreviewSnippet LAMBDA_PREVIEW = new PreviewSnippet(CodeFormatter.K_CLASS_BODY_DECLARATIONS, private final PreviewSnippet LAMBDA_PREVIEW = new PreviewSnippet(CodeFormatter.K_CLASS_BODY_DECLARATIONS,
"void foo() { auto f = []()->int{return 0;};}"); //$NON-NLS-1$ "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, private final PreviewSnippet INITIALIZER_LIST_PREVIEW = new PreviewSnippet(CodeFormatter.K_STATEMENTS,
"int array[]= {1, 2, 3};"); //$NON-NLS-1$ "int array[]= {1, 2, 3};"); //$NON-NLS-1$
@ -478,6 +481,7 @@ public final class WhiteSpaceOptions {
createLinkageTree(workingValues, declarations); createLinkageTree(workingValues, declarations);
// createConstructorTree(workingValues, declarations); // createConstructorTree(workingValues, declarations);
createLambdaDeclTree(workingValues, declarations); createLambdaDeclTree(workingValues, declarations);
createDeductionDeclTree(workingValues, declarations);
createMethodDeclTree(workingValues, declarations); createMethodDeclTree(workingValues, declarations);
createExceptionSpecificationTree(workingValues, declarations); createExceptionSpecificationTree(workingValues, declarations);
createLabelTree(workingValues, declarations); createLabelTree(workingValues, declarations);
@ -606,6 +610,9 @@ public final class WhiteSpaceOptions {
DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_POSTFIX_OPERATOR, OPERATOR_PREVIEW); DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_POSTFIX_OPERATOR, OPERATOR_PREVIEW);
createOption(parent, workingValues, FormatterMessages.WhiteSpaceOptions_lambda_arrow_operator, createOption(parent, workingValues, FormatterMessages.WhiteSpaceOptions_lambda_arrow_operator,
DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_BEFORE_LAMBDA_RETURN, LAMBDA_PREVIEW); 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) { 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); DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_POSTFIX_OPERATOR, OPERATOR_PREVIEW);
createOption(parent, workingValues, FormatterMessages.WhiteSpaceOptions_lambda_arrow_operator, createOption(parent, workingValues, FormatterMessages.WhiteSpaceOptions_lambda_arrow_operator,
DefaultCodeFormatterConstants.FORMATTER_INSERT_SPACE_AFTER_LAMBDA_RETURN, LAMBDA_PREVIEW); 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) { private void createAfterOpenBracketTree(Map<String, String> workingValues, final InnerNode parent) {
@ -1004,6 +1014,19 @@ public final class WhiteSpaceOptions {
return root; 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) { private InnerNode createLambdaDeclTree(Map<String, String> workingValues, InnerNode parent) {
final InnerNode root = new InnerNode(parent, workingValues, final InnerNode root = new InnerNode(parent, workingValues,
FormatterMessages.WhiteSpaceTabPage_lambda_expressions); FormatterMessages.WhiteSpaceTabPage_lambda_expressions);