mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-09-10 12:03:16 +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:
parent
1f89361032
commit
2dd5e7193d
9 changed files with 178 additions and 32 deletions
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -65,3 +65,59 @@ 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()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
scribe.printSpace();
|
||||
|
||||
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);
|
||||
}
|
||||
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());
|
||||
visitNodeIfNotNull(name);
|
||||
|
||||
if (simple.getDefaultType() != null){
|
||||
if (defaultArgument != null){
|
||||
scribe.print(EQUALS);
|
||||
simple.getDefaultType().accept(visitor);
|
||||
defaultArgument.accept(visitor);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue