1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-08-03 14:25:37 +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:
Thomas Corbat 2016-08-11 14:11:33 +02:00
parent 84a7eefeb2
commit 470561caec
7 changed files with 179 additions and 36 deletions

View file

@ -11956,4 +11956,74 @@ public class AST2CPPTests extends AST2TestBase {
public void testEnumDeclaredLaterInClass_491747() throws Exception {
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();
}
}

View file

@ -189,3 +189,10 @@ class Base
class TestClass final : public Base
{
};
//!decltype(auto)
//%CPP
decltype(auto) function()
{
decltype(auto) a = new decltype(auto)(5);
return a;
}

View file

@ -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
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@ -9,6 +9,7 @@
* Doug Schaefer (IBM) - Initial API and implementation
* Markus Schorn (Wind River Systems)
* Sergey Prigogin (Google)
* Thomas Corbat (IFS)
*******************************************************************************/
package org.eclipse.cdt.core.dom.ast;
@ -130,6 +131,12 @@ public interface IASTSimpleDeclSpecifier extends IASTDeclSpecifier {
*/
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
*/

View file

@ -43,6 +43,8 @@ public interface ISemanticProblem {
int TYPE_NOT_PERSISTED = 10005;
/** @since 5.6 */
int TYPE_ENUMERATION_EXPECTED = 10006;
/** @since 6.1 */
int TYPE_CANNOT_DEDUCE_DECLTYPE_AUTO_TYPE = 10007;
/**
* Returns the ID of the problem.

View file

@ -3365,10 +3365,15 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
}
// Otherwise we have a simple-decl-specifier.
simpleType= IASTSimpleDeclSpecifier.t_decltype;
consume(IToken.t_decltype);
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();
encounteredTypename= true;

View file

@ -2028,9 +2028,14 @@ public class CPPVisitor extends ASTQueries {
throw new IllegalArgumentException();
}
if (declSpec instanceof ICPPASTSimpleDeclSpecifier &&
((ICPPASTSimpleDeclSpecifier) declSpec).getType() == IASTSimpleDeclSpecifier.t_auto) {
return createAutoType(declSpec, declarator);
if (declSpec instanceof ICPPASTSimpleDeclSpecifier) {
ICPPASTSimpleDeclSpecifier simpleDeclSpecifier = (ICPPASTSimpleDeclSpecifier) declSpec;
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);
@ -2058,6 +2063,41 @@ public class CPPVisitor extends ASTQueries {
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) {
Set<IASTDeclSpecifier> recursionProtectionSet = autoTypeDeclSpecs.get();
if (!recursionProtectionSet.add(declSpec)) {
@ -2281,41 +2321,48 @@ public class CPPVisitor extends ASTQueries {
*/
private static IType getDeclType(ICPPASTSimpleDeclSpecifier spec) {
IASTExpression expr = spec.getDeclTypeExpression();
if (expr == null)
if (expr == 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;
if (expr instanceof IASTIdExpression) {
namedEntity= ((IASTIdExpression) expr).getName();
} else if (expr instanceof IASTFieldReference) {
namedEntity= ((IASTFieldReference) expr).getFieldName();
/**
* Computes the type for an expression in decltype(expr) context.
*/
private static IType getDeclType(IASTExpression expr) {
IASTName namedEntity= null;
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) {
IBinding b= namedEntity.resolvePreBinding();
if (b instanceof IType) {
return (IType) b;
}
if (b instanceof IVariable) {
return ((IVariable) b).getType();
}
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();
if (spec.getType() == IASTSimpleDeclSpecifier.t_decltype) {
switch (expr.getValueCategory()) {
case XVALUE:
type= new CPPReferenceType(type, true);
break;
case LVALUE:
type= new CPPReferenceType(type, false);
break;
case PRVALUE:
break;
}
switch (expr.getValueCategory()) {
case XVALUE:
type= new CPPReferenceType(type, true);
break;
case LVALUE:
type= new CPPReferenceType(type, false);
break;
case PRVALUE:
break;
}
return type;
}

View file

@ -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
* All rights reserved. This program and the accompanying materials
* 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;
break;
case IASTSimpleDeclSpecifier.t_decltype:
case IASTSimpleDeclSpecifier.t_decltype_auto:
if (isCpp)
return Keywords.DECLTYPE;
break;
@ -382,6 +383,10 @@ public class DeclSpecWriter extends NodeWriter {
scribe.print('(');
visitNodeIfNotNull(simpDeclSpec.getDeclTypeExpression());
scribe.print(')');
} else if (simpDeclSpec.getType() == IASTSimpleDeclSpecifier.t_decltype_auto) {
scribe.print('(');
scribe.print(Keywords.AUTO);
scribe.print(')');
}
}