1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-09-10 03:53:21 +02:00

537217: [C++17] Add support for typename keyword for template template parameters

This patch allows for the 'typename' keyword to be used in
template-template template parameter declarations. Additionally, this
patch also fixes an issue in the writer, which caused the ellipsis in
variadic template-template template parameter declaration to be dropped.

Change-Id: I8f68e6053b2b8848b35d1cf6d25d7f4b5b9d396d
Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=537217
Signed-off-by: Felix Morgner <fmorgner@hsr.ch>
This commit is contained in:
Felix Morgner 2018-07-20 13:17:53 +02:00 committed by Nathan Ridge
parent 1f89361032
commit 2dd5e7193d
9 changed files with 178 additions and 32 deletions

View file

@ -0,0 +1,37 @@
/*******************************************************************************
* Copyright (c) 2018 Felix Morgner
* 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 (IFS Institute for Software) - Initial implementation
*******************************************************************************/
package org.eclipse.cdt.core.parser.tests.ast2.cxx17;
import org.eclipse.cdt.core.parser.tests.ast2.AST2CPPTestBase;
import junit.framework.TestSuite;
public class TemplateTemplateTypenameTests extends AST2CPPTestBase {
public static TestSuite suite() {
return suite(TemplateTemplateTypenameTests.class);
}
// template<template<typename> typename T>
// void f(T<int> param) {
// }
public void testFunctionTemplateWithTemplateTemplateParameterWithTypenameInsteadOfClass_537217() throws Exception {
parseAndCheckBindings();
}
// template<template<typename> typename U>
// class C {
// U<int> mem;
// };
public void testClassTemplateWithTemplateTemplateParameterWithTypenameInsteadOfClass_537217() throws Exception {
parseAndCheckBindings();
}
}

View file

@ -64,4 +64,60 @@ template<typename T> struct S
int f()
{
return S<int>::template c<100>;
}
}
//!Type Template Parameter with class
//%CPP
template<class >
void f()
{
}
//!Type Template Parameter with typename
//%CPP
template<typename >
void f()
{
}
//!Variadic Type Template Parameter with class
//%CPP
template<class... >
void f()
{
}
//!Variadic Type Template Parameter with typename
//%CPP
template<typename... >
void f()
{
}
//!Template-template Template Parameter with class
//%CPP
template<template <typename > class >
void f()
{
}
//!Template-template Template Parameter with typename
//%CPP
template<template <typename > typename >
void f()
{
}
//!Variadic Template-template Template Parameter with class
//%CPP
template<template <typename > class... >
void f()
{
}
//!Variadic Template-template Template Parameter with typename
//%CPP
template<template <typename > typename... >
void f()
{
}

View file

@ -47,7 +47,7 @@ public interface ICPPASTSimpleTypeTemplateParameter extends ICPPASTTemplateParam
/**
* Get the parameter type.
* Get the type of the type parameter (either {@link #st_class} or {@link #st_typename}).
*/
public int getParameterType();
@ -62,7 +62,9 @@ public interface ICPPASTSimpleTypeTemplateParameter extends ICPPASTTemplateParam
public IASTTypeId getDefaultType();
/**
* Set the parameter type.
* Set the type of the type parameter.
*
* @param value The type of the type parameter (either {@link #st_class} or {@link #st_typename})
*/
public void setParameterType(int value);

View file

@ -43,11 +43,29 @@ public interface ICPPASTTemplatedTypeTemplateParameter extends ICPPASTTemplatePa
public static final ASTNodeProperty DEFAULT_VALUE = new ASTNodeProperty(
"ICPPASTTemplateTypeTemplateParameter.DEFAULT_VALUE [IASTExpression]"); //$NON-NLS-1$
/**
* <code>tt_class</code> represents a class.
* @since 6.6
*/
public static final int tt_class = 1;
/**
* <code>tt_typename</code> represents a typename.
* @since 6.6
*/
public static final int tt_typename = 2;
/**
* Get the nested template parameters.
*/
public ICPPASTTemplateParameter[] getTemplateParameters();
/**
* Get the type of the template-template parameter (either {@link #tt_class} or {@link #tt_typename}).
* @since 6.6
*/
public int getParameterType();
/**
* Get the (optional) name of this template template parameter. In case there is no name an
* empty name is returned.
@ -84,6 +102,13 @@ public interface ICPPASTTemplatedTypeTemplateParameter extends ICPPASTTemplatePa
*/
public void setIsParameterPack(boolean val);
/**
* Set the type of the template-template parameter.
* @param type The type of the template-template parameter (either {@link #tt_class} or {@link #tt_typename})
* @since 6.6
*/
public void setParameterType(int type);
/**
* Set the name of this template template parameter.
*/

View file

@ -358,6 +358,11 @@ public interface ICPPNodeFactory extends INodeFactory {
public ICPPASTTemplatedTypeTemplateParameter newTemplatedTypeTemplateParameter(IASTName name, IASTExpression defaultValue);
/**
* @since 6.6
*/
public ICPPASTTemplatedTypeTemplateParameter newTemplatedTypeTemplateParameter(int type, IASTName name, IASTExpression defaultValue);
public ICPPASTTemplateId newTemplateId(IASTName templateName);
public ICPPASTTemplateSpecialization newTemplateSpecialization(IASTDeclaration declaration);

View file

@ -30,6 +30,7 @@ public class CPPASTTemplatedTypeTemplateParameter extends ASTNode implements
private ICPPASTTemplateParameter [] fNestedParameters = null;
private boolean fIsParameterPack;
private boolean fUsesKeywordClass;
private IASTName fName;
private IASTExpression fDefaultValue;
private CPPTemplateTemplateParameterScope fScope;
@ -38,6 +39,11 @@ public class CPPASTTemplatedTypeTemplateParameter extends ASTNode implements
}
public CPPASTTemplatedTypeTemplateParameter(IASTName name, IASTExpression defaultValue) {
this(tt_class, name, defaultValue);
}
public CPPASTTemplatedTypeTemplateParameter(int type, IASTName name, IASTExpression defaultValue) {
fUsesKeywordClass = type == tt_class;
setName(name);
setDefaultValue(defaultValue);
}
@ -52,6 +58,7 @@ public class CPPASTTemplatedTypeTemplateParameter extends ASTNode implements
CPPASTTemplatedTypeTemplateParameter copy = new CPPASTTemplatedTypeTemplateParameter();
copy.setName(fName == null ? null : fName.copy(style));
copy.setDefaultValue(fDefaultValue == null ? null : fDefaultValue.copy(style));
copy.fUsesKeywordClass = fUsesKeywordClass;
copy.fIsParameterPack = fIsParameterPack;
for (ICPPASTTemplateParameter param : getTemplateParameters())
copy.addTemplateParameter(param == null ? null : param.copy(style));
@ -95,6 +102,17 @@ public class CPPASTTemplatedTypeTemplateParameter extends ASTNode implements
return fIsParameterPack;
}
@Override
public int getParameterType() {
return fUsesKeywordClass ? tt_class : tt_typename;
}
@Override
public void setParameterType(int type) {
assertNotFrozen();
fUsesKeywordClass = type == tt_class;
}
@Override
public IASTName getName() {
return fName;

View file

@ -774,6 +774,11 @@ public class CPPNodeFactory extends NodeFactory implements ICPPNodeFactory {
return new CPPASTTemplatedTypeTemplateParameter(name, defaultValue);
}
@Override
public ICPPASTTemplatedTypeTemplateParameter newTemplatedTypeTemplateParameter(int type, IASTName name, IASTExpression defaultValue) {
return new CPPASTTemplatedTypeTemplateParameter(type, name, defaultValue);
}
@Override
public ICPPASTTemplateId newTemplateId(IASTName templateName) {
return new CPPASTTemplateId(templateName);

View file

@ -2540,7 +2540,13 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
consume(IToken.tLT);
List<ICPPASTTemplateParameter> tparList = templateParameterList(new ArrayList<>());
consume(IToken.tGT, IToken.tGT_in_SHIFTR);
int endOffset = consume(IToken.t_class).getEndOffset();
int kind = LT(1);
if(kind != IToken.t_class && kind != IToken.t_typename) {
throw backtrack;
}
int endOffset = consume(kind).getEndOffset();
if (LT(1) == IToken.tELLIPSIS) {
parameterPack= true;
@ -2564,6 +2570,7 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
ICPPASTTemplatedTypeTemplateParameter tpar = getNodeFactory().newTemplatedTypeTemplateParameter(identifierName, defaultValue);
tpar.setIsParameterPack(parameterPack);
tpar.setParameterType(kind == IToken.t_class ? ICPPASTTemplatedTypeTemplateParameter.tt_class : ICPPASTTemplatedTypeTemplateParameter.tt_typename);
setRange(tpar, start.getOffset(), endOffset);
for (int i = 0; i < tparList.size(); ++i) {

View file

@ -11,6 +11,8 @@
*******************************************************************************/
package org.eclipse.cdt.internal.core.dom.rewrite.astwriter;
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.ICPPASTParameterDeclaration;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTSimpleTypeTemplateParameter;
@ -28,7 +30,7 @@ import org.eclipse.cdt.internal.core.dom.rewrite.commenthandler.NodeCommentMap;
* @author Emanuel Graf IFS
*/
public class TemplateParameterWriter extends NodeWriter {
private static final String GREATER_THAN_CLASS = "> class"; //$NON-NLS-1$
private static final String GREATER_THAN = ">"; //$NON-NLS-1$
private static final String TEMPLATE_LESS_THAN = "template <"; //$NON-NLS-1$
/**
@ -43,7 +45,9 @@ public class TemplateParameterWriter extends NodeWriter {
if (parameter instanceof ICPPASTParameterDeclaration) {
((IASTParameterDeclaration)((ICPPASTParameterDeclaration) parameter)).accept(visitor);
} else if (parameter instanceof ICPPASTSimpleTypeTemplateParameter) {
writeSimpleTypeTemplateParameter((ICPPASTSimpleTypeTemplateParameter) parameter);
ICPPASTSimpleTypeTemplateParameter simple = (ICPPASTSimpleTypeTemplateParameter) parameter;
writeTemplateParameter(simple.getParameterType() == ICPPASTSimpleTypeTemplateParameter.st_class,
simple.isParameterPack(), simple.getName(), simple.getDefaultType());
} else if (parameter instanceof ICPPASTTemplatedTypeTemplateParameter) {
writeTemplatedTypeTemplateParameter((ICPPASTTemplatedTypeTemplateParameter) parameter);
}
@ -53,38 +57,25 @@ public class TemplateParameterWriter extends NodeWriter {
scribe.print(TEMPLATE_LESS_THAN);
ICPPASTTemplateParameter[] params = templated.getTemplateParameters();
writeNodeList(params);
scribe.print(GREATER_THAN_CLASS);
if (templated.getName()!=null){
scribe.printSpace();
templated.getName().accept(visitor);
}
if (templated.getDefaultValue() != null){
scribe.print(EQUALS);
templated.getDefaultValue().accept(visitor);
}
scribe.print(GREATER_THAN);
scribe.printSpace();
writeTemplateParameter(templated.getParameterType() == ICPPASTTemplatedTypeTemplateParameter.tt_class,
templated.isParameterPack(), templated.getName(), templated.getDefaultValue());
}
private void writeSimpleTypeTemplateParameter(ICPPASTSimpleTypeTemplateParameter simple) {
switch (simple.getParameterType()) {
case ICPPASTSimpleTypeTemplateParameter.st_class:
scribe.print(Keywords.CLASS);
break;
case ICPPASTSimpleTypeTemplateParameter.st_typename:
scribe.print(Keywords.TYPENAME);
break;
}
if (simple.isParameterPack()) {
private void writeTemplateParameter(boolean usesClass, boolean isVariadic, IASTName name, IASTNode defaultArgument) {
scribe.print(usesClass ? Keywords.CLASS : Keywords.TYPENAME);
if (isVariadic) {
scribe.print(VAR_ARGS);
}
scribe.printSpace();
visitNodeIfNotNull(simple.getName());
if (simple.getDefaultType() != null){
visitNodeIfNotNull(name);
if (defaultArgument != null){
scribe.print(EQUALS);
simple.getDefaultType().accept(visitor);
defaultArgument.accept(visitor);
}
}
}