mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-06 07:45:50 +02:00
Bug Bug 482225 - decltype(auto) not parsed
* Adapted the parser to cope with decltype(auto) * Extended IASTSimpleDeclSpecifier to have a kind for decltype(auto) * Added tests (syntactic recognition and type deduction for variables) * Modified DeclSpecWriter to cope with the decltype(auto) kind simple decl specifier Change-Id: Ib1ded823027d124cef35e9d6355c0f48f57709a0 Signed-off-by: Thomas Corbat <tcorbat@hsr.ch>
This commit is contained in:
parent
84a7eefeb2
commit
470561caec
7 changed files with 179 additions and 36 deletions
|
@ -11956,4 +11956,74 @@ public class AST2CPPTests extends AST2TestBase {
|
||||||
public void testEnumDeclaredLaterInClass_491747() throws Exception {
|
public void testEnumDeclaredLaterInClass_491747() throws Exception {
|
||||||
parseAndCheckBindings();
|
parseAndCheckBindings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// namespace std {
|
||||||
|
// template<typename T> class initializer_list;
|
||||||
|
// }
|
||||||
|
// struct A {};
|
||||||
|
// A&& foo();
|
||||||
|
// A a;
|
||||||
|
// decltype(auto) b = a; // decltype(b) is A
|
||||||
|
// decltype(auto) c(a); // decltype(c) is A
|
||||||
|
// decltype(auto) d = (a); // decltype(d) is A &
|
||||||
|
// decltype(auto) e = foo(); // decltype(e) is A &&
|
||||||
|
// static decltype(auto) f = 0.0; // decltype(f) is double
|
||||||
|
// decltype(auto) g = &a, h = &b; // decltype(g) and decltype(h) are A *
|
||||||
|
// decltype(auto) i = { 'a', 'b' }; // Error - cannot deduce decltype(auto) from initializer list.
|
||||||
|
// decltype(auto) j{42}; // Valid since C++17: decltype(j) is int
|
||||||
|
// decltype(auto) k = new decltype(auto)(1L); // decltype(j) is long int *
|
||||||
|
// decltype(auto) l; // Error - missing initializer.
|
||||||
|
public void testDecltypeAutoVariableTypes_482225() throws Exception {
|
||||||
|
String code = getAboveComment();
|
||||||
|
BindingAssertionHelper bh = new BindingAssertionHelper(code, true);
|
||||||
|
|
||||||
|
ICPPVariable b = bh.assertNonProblem("b =", 1);
|
||||||
|
assertEquals("A", ASTTypeUtil.getType(b.getType()));
|
||||||
|
|
||||||
|
ICPPVariable c = bh.assertNonProblem("c(a)", 1);
|
||||||
|
assertEquals("A", ASTTypeUtil.getType(c.getType()));
|
||||||
|
|
||||||
|
ICPPVariable d = bh.assertNonProblem("d =", 1);
|
||||||
|
assertEquals("A &", ASTTypeUtil.getType(d.getType()));
|
||||||
|
|
||||||
|
ICPPVariable e = bh.assertNonProblem("e =", 1);
|
||||||
|
assertEquals("A &&", ASTTypeUtil.getType(e.getType()));
|
||||||
|
|
||||||
|
ICPPVariable f = bh.assertNonProblem("f =", 1);
|
||||||
|
assertEquals("double", ASTTypeUtil.getType(f.getType()));
|
||||||
|
|
||||||
|
ICPPVariable g = bh.assertNonProblem("g =", 1);
|
||||||
|
assertEquals("A *", ASTTypeUtil.getType(g.getType()));
|
||||||
|
|
||||||
|
ICPPVariable h = bh.assertNonProblem("h =", 1);
|
||||||
|
assertEquals("A *", ASTTypeUtil.getType(h.getType()));
|
||||||
|
|
||||||
|
ICPPVariable i = bh.assertNonProblem("i =", 1);
|
||||||
|
IProblemType iType = (IProblemType) i.getType();
|
||||||
|
assertEquals(ISemanticProblem.TYPE_CANNOT_DEDUCE_DECLTYPE_AUTO_TYPE, iType.getID());
|
||||||
|
|
||||||
|
ICPPVariable j = bh.assertNonProblem("j{42}", 1);
|
||||||
|
assertEquals("int", ASTTypeUtil.getType(j.getType()));
|
||||||
|
|
||||||
|
ICPPVariable k = bh.assertNonProblem("k =", 1);
|
||||||
|
assertEquals("long int *", ASTTypeUtil.getType(k.getType()));
|
||||||
|
|
||||||
|
ICPPVariable l = bh.assertNonProblem("l;", 1);
|
||||||
|
IProblemType lType = (IProblemType) l.getType();
|
||||||
|
assertEquals(ISemanticProblem.TYPE_CANNOT_DEDUCE_DECLTYPE_AUTO_TYPE, lType.getID());
|
||||||
|
}
|
||||||
|
|
||||||
|
// auto foo() -> decltype(auto) {
|
||||||
|
// return 23.0;
|
||||||
|
// }
|
||||||
|
public void testDecltypeAutoTrailingReturnType_482225() throws Exception {
|
||||||
|
parseAndCheckBindings();
|
||||||
|
}
|
||||||
|
|
||||||
|
// decltype(auto) foo() {
|
||||||
|
// return 23.0;
|
||||||
|
// }
|
||||||
|
public void testDecltypeAutoReturnType_482225() throws Exception {
|
||||||
|
parseAndCheckBindings();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -189,3 +189,10 @@ class Base
|
||||||
class TestClass final : public Base
|
class TestClass final : public Base
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
//!decltype(auto)
|
||||||
|
//%CPP
|
||||||
|
decltype(auto) function()
|
||||||
|
{
|
||||||
|
decltype(auto) a = new decltype(auto)(5);
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2004, 2015 IBM Corporation and others.
|
* Copyright (c) 2004, 2016 IBM Corporation and others.
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
* which accompanies this distribution, and is available at
|
* which accompanies this distribution, and is available at
|
||||||
|
@ -9,6 +9,7 @@
|
||||||
* Doug Schaefer (IBM) - Initial API and implementation
|
* Doug Schaefer (IBM) - Initial API and implementation
|
||||||
* Markus Schorn (Wind River Systems)
|
* Markus Schorn (Wind River Systems)
|
||||||
* Sergey Prigogin (Google)
|
* Sergey Prigogin (Google)
|
||||||
|
* Thomas Corbat (IFS)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.core.dom.ast;
|
package org.eclipse.cdt.core.dom.ast;
|
||||||
|
|
||||||
|
@ -130,6 +131,12 @@ public interface IASTSimpleDeclSpecifier extends IASTDeclSpecifier {
|
||||||
*/
|
*/
|
||||||
public static final int t_decimal128 = 17;
|
public static final int t_decimal128 = 17;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <code>decltype(auto) c = expression;</code>
|
||||||
|
* @since 6.1
|
||||||
|
*/
|
||||||
|
public static final int t_decltype_auto = 18;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @since 5.1
|
* @since 5.1
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -43,6 +43,8 @@ public interface ISemanticProblem {
|
||||||
int TYPE_NOT_PERSISTED = 10005;
|
int TYPE_NOT_PERSISTED = 10005;
|
||||||
/** @since 5.6 */
|
/** @since 5.6 */
|
||||||
int TYPE_ENUMERATION_EXPECTED = 10006;
|
int TYPE_ENUMERATION_EXPECTED = 10006;
|
||||||
|
/** @since 6.1 */
|
||||||
|
int TYPE_CANNOT_DEDUCE_DECLTYPE_AUTO_TYPE = 10007;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the ID of the problem.
|
* Returns the ID of the problem.
|
||||||
|
|
|
@ -3365,10 +3365,15 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise we have a simple-decl-specifier.
|
// Otherwise we have a simple-decl-specifier.
|
||||||
simpleType= IASTSimpleDeclSpecifier.t_decltype;
|
|
||||||
consume(IToken.t_decltype);
|
consume(IToken.t_decltype);
|
||||||
consume(IToken.tLPAREN);
|
consume(IToken.tLPAREN);
|
||||||
typeofExpression= expression();
|
if (LT(1) == IToken.t_auto) {
|
||||||
|
simpleType= IASTSimpleDeclSpecifier.t_decltype_auto;
|
||||||
|
consume(IToken.t_auto);
|
||||||
|
} else {
|
||||||
|
simpleType= IASTSimpleDeclSpecifier.t_decltype;
|
||||||
|
typeofExpression= expression();
|
||||||
|
}
|
||||||
endOffset= consumeOrEOC(IToken.tRPAREN).getEndOffset();
|
endOffset= consumeOrEOC(IToken.tRPAREN).getEndOffset();
|
||||||
|
|
||||||
encounteredTypename= true;
|
encounteredTypename= true;
|
||||||
|
|
|
@ -2028,9 +2028,14 @@ public class CPPVisitor extends ASTQueries {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (declSpec instanceof ICPPASTSimpleDeclSpecifier &&
|
if (declSpec instanceof ICPPASTSimpleDeclSpecifier) {
|
||||||
((ICPPASTSimpleDeclSpecifier) declSpec).getType() == IASTSimpleDeclSpecifier.t_auto) {
|
ICPPASTSimpleDeclSpecifier simpleDeclSpecifier = (ICPPASTSimpleDeclSpecifier) declSpec;
|
||||||
return createAutoType(declSpec, declarator);
|
int declSpecifierType = simpleDeclSpecifier.getType();
|
||||||
|
if (declSpecifierType == IASTSimpleDeclSpecifier.t_auto) {
|
||||||
|
return createAutoType(declSpec, declarator);
|
||||||
|
} else if (declSpecifierType == IASTSimpleDeclSpecifier.t_decltype_auto) {
|
||||||
|
return createDecltypeAutoType(declarator, simpleDeclSpecifier);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IType type = createType(declSpec);
|
IType type = createType(declSpec);
|
||||||
|
@ -2058,6 +2063,41 @@ public class CPPVisitor extends ASTQueries {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static IType createDecltypeAutoType(IASTDeclarator declarator, ICPPASTSimpleDeclSpecifier simpleDeclSpecifier) {
|
||||||
|
IASTInitializerClause initializerClause = getInitializerClauseForDecltypeAuto(declarator);
|
||||||
|
if (initializerClause instanceof IASTExpression) {
|
||||||
|
return getDeclType((IASTExpression) initializerClause);
|
||||||
|
}
|
||||||
|
return new ProblemType(ISemanticProblem.TYPE_CANNOT_DEDUCE_DECLTYPE_AUTO_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IASTInitializerClause getInitializerClauseForDecltypeAuto(IASTDeclarator declarator) {
|
||||||
|
IASTInitializer initializer = declarator.getInitializer();
|
||||||
|
if (initializer == null) {
|
||||||
|
ICPPASTNewExpression newExpression = CPPVisitor.findAncestorWithType(declarator, ICPPASTNewExpression.class);
|
||||||
|
if (newExpression != null) {
|
||||||
|
initializer = newExpression.getInitializer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (initializer instanceof IASTEqualsInitializer) {
|
||||||
|
return ((IASTEqualsInitializer) initializer).getInitializerClause();
|
||||||
|
} else if (initializer instanceof ICPPASTConstructorInitializer) {
|
||||||
|
ICPPASTConstructorInitializer constructorInitializer = (ICPPASTConstructorInitializer) initializer;
|
||||||
|
IASTInitializerClause[] arguments = constructorInitializer.getArguments();
|
||||||
|
if (arguments.length == 1) {
|
||||||
|
return arguments[0];
|
||||||
|
}
|
||||||
|
} else if (initializer instanceof IASTInitializerList) {
|
||||||
|
IASTInitializerList initializerList = (IASTInitializerList) initializer;
|
||||||
|
IASTInitializerClause[] clauses = initializerList.getClauses();
|
||||||
|
if (clauses.length == 1) {
|
||||||
|
return clauses[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private static IType createAutoType(final IASTDeclSpecifier declSpec, IASTDeclarator declarator) {
|
private static IType createAutoType(final IASTDeclSpecifier declSpec, IASTDeclarator declarator) {
|
||||||
Set<IASTDeclSpecifier> recursionProtectionSet = autoTypeDeclSpecs.get();
|
Set<IASTDeclSpecifier> recursionProtectionSet = autoTypeDeclSpecs.get();
|
||||||
if (!recursionProtectionSet.add(declSpec)) {
|
if (!recursionProtectionSet.add(declSpec)) {
|
||||||
|
@ -2281,41 +2321,48 @@ public class CPPVisitor extends ASTQueries {
|
||||||
*/
|
*/
|
||||||
private static IType getDeclType(ICPPASTSimpleDeclSpecifier spec) {
|
private static IType getDeclType(ICPPASTSimpleDeclSpecifier spec) {
|
||||||
IASTExpression expr = spec.getDeclTypeExpression();
|
IASTExpression expr = spec.getDeclTypeExpression();
|
||||||
if (expr == null)
|
if (expr == null) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
int specifierType = spec.getType();
|
||||||
|
if (specifierType == IASTSimpleDeclSpecifier.t_decltype) {
|
||||||
|
return getDeclType(expr);
|
||||||
|
}
|
||||||
|
return expr.getExpressionType();
|
||||||
|
}
|
||||||
|
|
||||||
if (spec.getType() == IASTSimpleDeclSpecifier.t_decltype) {
|
/**
|
||||||
IASTName namedEntity= null;
|
* Computes the type for an expression in decltype(expr) context.
|
||||||
if (expr instanceof IASTIdExpression) {
|
*/
|
||||||
namedEntity= ((IASTIdExpression) expr).getName();
|
private static IType getDeclType(IASTExpression expr) {
|
||||||
} else if (expr instanceof IASTFieldReference) {
|
IASTName namedEntity= null;
|
||||||
namedEntity= ((IASTFieldReference) expr).getFieldName();
|
if (expr instanceof IASTIdExpression) {
|
||||||
|
namedEntity= ((IASTIdExpression) expr).getName();
|
||||||
|
} else if (expr instanceof IASTFieldReference) {
|
||||||
|
namedEntity= ((IASTFieldReference) expr).getFieldName();
|
||||||
|
}
|
||||||
|
if (namedEntity != null) {
|
||||||
|
IBinding b= namedEntity.resolvePreBinding();
|
||||||
|
if (b instanceof IType) {
|
||||||
|
return (IType) b;
|
||||||
}
|
}
|
||||||
if (namedEntity != null) {
|
if (b instanceof IVariable) {
|
||||||
IBinding b= namedEntity.resolvePreBinding();
|
return ((IVariable) b).getType();
|
||||||
if (b instanceof IType) {
|
}
|
||||||
return (IType) b;
|
if (b instanceof IFunction) {
|
||||||
}
|
return ((IFunction) b).getType();
|
||||||
if (b instanceof IVariable) {
|
|
||||||
return ((IVariable) b).getType();
|
|
||||||
}
|
|
||||||
if (b instanceof IFunction) {
|
|
||||||
return ((IFunction) b).getType();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IType type = expr.getExpressionType();
|
IType type = expr.getExpressionType();
|
||||||
if (spec.getType() == IASTSimpleDeclSpecifier.t_decltype) {
|
switch (expr.getValueCategory()) {
|
||||||
switch (expr.getValueCategory()) {
|
case XVALUE:
|
||||||
case XVALUE:
|
type= new CPPReferenceType(type, true);
|
||||||
type= new CPPReferenceType(type, true);
|
break;
|
||||||
break;
|
case LVALUE:
|
||||||
case LVALUE:
|
type= new CPPReferenceType(type, false);
|
||||||
type= new CPPReferenceType(type, false);
|
break;
|
||||||
break;
|
case PRVALUE:
|
||||||
case PRVALUE:
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Copyright (c) 2008, 2015 Institute for Software, HSR Hochschule fuer Technik
|
* Copyright (c) 2008, 2016 Institute for Software, HSR Hochschule fuer Technik
|
||||||
* Rapperswil, University of applied sciences and others
|
* Rapperswil, University of applied sciences and others
|
||||||
* All rights reserved. This program and the accompanying materials
|
* All rights reserved. This program and the accompanying materials
|
||||||
* are made available under the terms of the Eclipse Public License v1.0
|
* are made available under the terms of the Eclipse Public License v1.0
|
||||||
|
@ -123,6 +123,7 @@ public class DeclSpecWriter extends NodeWriter {
|
||||||
return Keywords.TYPEOF;
|
return Keywords.TYPEOF;
|
||||||
break;
|
break;
|
||||||
case IASTSimpleDeclSpecifier.t_decltype:
|
case IASTSimpleDeclSpecifier.t_decltype:
|
||||||
|
case IASTSimpleDeclSpecifier.t_decltype_auto:
|
||||||
if (isCpp)
|
if (isCpp)
|
||||||
return Keywords.DECLTYPE;
|
return Keywords.DECLTYPE;
|
||||||
break;
|
break;
|
||||||
|
@ -382,6 +383,10 @@ public class DeclSpecWriter extends NodeWriter {
|
||||||
scribe.print('(');
|
scribe.print('(');
|
||||||
visitNodeIfNotNull(simpDeclSpec.getDeclTypeExpression());
|
visitNodeIfNotNull(simpDeclSpec.getDeclTypeExpression());
|
||||||
scribe.print(')');
|
scribe.print(')');
|
||||||
|
} else if (simpDeclSpec.getType() == IASTSimpleDeclSpecifier.t_decltype_auto) {
|
||||||
|
scribe.print('(');
|
||||||
|
scribe.print(Keywords.AUTO);
|
||||||
|
scribe.print(')');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue