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:
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 {
|
||||
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
|
||||
{
|
||||
};
|
||||
//!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
|
||||
* 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
|
||||
*/
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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(')');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue