mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Array size determined by initializer expression, bug 294144.
This commit is contained in:
parent
fa2c3fcdd0
commit
8120ebe44f
7 changed files with 115 additions and 73 deletions
|
@ -7672,6 +7672,21 @@ public class AST2CPPTests extends AST2BaseTest {
|
|||
public void testCVQualifiersWithArrays_293982() throws Exception {
|
||||
final String code = getAboveComment();
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
}
|
||||
}
|
||||
|
||||
// template <typename T, int N> char (&func(T (&array)[N]))[N];
|
||||
// void f(const int (&a)[1]) {}
|
||||
// typedef int TA[];
|
||||
// TA a = { 0 };
|
||||
// int b[1];
|
||||
//
|
||||
// void test() {
|
||||
// f(a); func(a);
|
||||
// f(b); func(b);
|
||||
// }
|
||||
public void testArrayTypeSizeFromInitializer_294144() throws Exception {
|
||||
final String code = getAboveComment();
|
||||
parseAndCheckBindings(code, ParserLanguage.CPP);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@ package org.eclipse.cdt.core.dom.ast;
|
|||
|
||||
/**
|
||||
* This is an an initializer that is a list of initializers.
|
||||
* For example as in:
|
||||
* <pre> int a[]= {1,2,3}; </pre>
|
||||
*
|
||||
* @noextend This interface is not intended to be extended by clients.
|
||||
* @noimplement This interface is not intended to be implemented by clients.
|
||||
|
@ -26,20 +28,25 @@ public interface IASTInitializerList extends IASTInitializer {
|
|||
"IASTInitializerList.NESTED_INITIALIZER - sub-IASTInitializer for IASTInitializerList"); //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Get the list of initializers.
|
||||
*
|
||||
* @return <code>IASTInitializer[]</code> array of initializers
|
||||
* Returns the size of the initializer list, including trivial initializers. This size may
|
||||
* be larger than the length of the array returned by {@link #getInitializers()}.
|
||||
* @since 5.2
|
||||
*/
|
||||
public int getSize();
|
||||
|
||||
/**
|
||||
* Returns the list of initializers. Depending on how the ast was created, this may omit
|
||||
* trivial initializers in order to save memory.
|
||||
*/
|
||||
public IASTInitializer[] getInitializers();
|
||||
|
||||
/**
|
||||
* Add an initializer to the initializer list.
|
||||
*
|
||||
* @param initializer
|
||||
* <code>IASTInitializer</code>
|
||||
* Add an initializer to the initializer list. Depending on how the AST is created the
|
||||
* initializer may be <code>null</code>. A <code>null</code> initializer will not be returned
|
||||
* by {@link #getInitializers()}, however it contributes to the actual element count (#getSize()).
|
||||
*/
|
||||
public void addInitializer(IASTInitializer initializer);
|
||||
|
||||
|
||||
/**
|
||||
* @since 5.1
|
||||
*/
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2005, 2008 IBM Corporation and others.
|
||||
* Copyright (c) 2005, 2009 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
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM Rational Software - Initial API and implementation
|
||||
* Markus Schorn (Wind River Systems)
|
||||
* Yuan Zhang / Beth Tibbitts (IBM Research)
|
||||
* John Camelon (IBM Rational Software) - Initial API and implementation
|
||||
* Markus Schorn (Wind River Systems)
|
||||
* Yuan Zhang / Beth Tibbitts (IBM Research)
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.c;
|
||||
|
||||
|
@ -19,23 +19,34 @@ import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
||||
|
||||
/**
|
||||
* @author jcamelon
|
||||
* e.g.: int a[]= {1,2,3};
|
||||
*/
|
||||
public class CASTInitializerList extends ASTNode implements IASTInitializerList {
|
||||
|
||||
private IASTInitializer [] initializers = null;
|
||||
private int initializersPos=-1;
|
||||
private int actualSize;
|
||||
|
||||
public CASTInitializerList copy() {
|
||||
CASTInitializerList copy = new CASTInitializerList();
|
||||
for(IASTInitializer initializer : getInitializers())
|
||||
copy.addInitializer(initializer == null ? null : initializer.copy());
|
||||
copy.setOffsetAndLength(this);
|
||||
copy.actualSize= getSize();
|
||||
return copy;
|
||||
}
|
||||
|
||||
public IASTInitializer[] getInitializers() {
|
||||
if( initializers == null ) return IASTInitializer.EMPTY_INITIALIZER_ARRAY;
|
||||
initializers = (IASTInitializer[]) ArrayUtil.removeNullsAfter( IASTInitializer.class, initializers, initializersPos );
|
||||
return initializers;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return actualSize;
|
||||
}
|
||||
|
||||
public IASTInitializer[] getInitializers() {
|
||||
if (initializers == null)
|
||||
return IASTInitializer.EMPTY_INITIALIZER_ARRAY;
|
||||
initializers = ArrayUtil.trimAt(IASTInitializer.class, initializers, initializersPos);
|
||||
return initializers;
|
||||
}
|
||||
|
||||
public void addInitializer( IASTInitializer d ) {
|
||||
assertNotFrozen();
|
||||
|
@ -44,10 +55,9 @@ public class CASTInitializerList extends ASTNode implements IASTInitializerList
|
|||
d.setParent(this);
|
||||
d.setPropertyInParent(NESTED_INITIALIZER);
|
||||
}
|
||||
actualSize++;
|
||||
}
|
||||
|
||||
private IASTInitializer [] initializers = null;
|
||||
private int initializersPos=-1;
|
||||
|
||||
@Override
|
||||
public boolean accept( ASTVisitor action ){
|
||||
|
|
|
@ -175,9 +175,8 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
|
|||
if (designator == null) {
|
||||
IASTInitializer initializer= cInitializerClause(true);
|
||||
// depending on value of skipTrivialItemsInCompoundInitializers initializer may be null
|
||||
if (initializer != null) {
|
||||
result.addInitializer(initializer);
|
||||
}
|
||||
// in any way add the initializer such that the actual size can be tracked.
|
||||
result.addInitializer(initializer);
|
||||
} else {
|
||||
if (LT(1) == IToken.tASSIGN)
|
||||
consume();
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2004, 2008 IBM Corporation and others.
|
||||
* Copyright (c) 2004, 2009 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
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM - Initial API and implementation
|
||||
* John Camelon (IBM) - Initial API and implementation
|
||||
* Markus Schorn (Wind River Systems)
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||
|
||||
|
@ -17,37 +18,45 @@ import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
||||
|
||||
/**
|
||||
* @author jcamelon
|
||||
* e.g.: int a[]= {1,2,3};
|
||||
*/
|
||||
public class CPPASTInitializerList extends ASTNode implements IASTInitializerList {
|
||||
|
||||
private IASTInitializer [] initializers = null;
|
||||
private int initializersPos=-1;
|
||||
private int actualLength;
|
||||
|
||||
public CPPASTInitializerList copy() {
|
||||
CPPASTInitializerList copy = new CPPASTInitializerList();
|
||||
for(IASTInitializer initializer : getInitializers())
|
||||
copy.addInitializer(initializer == null ? null : initializer.copy());
|
||||
copy.setOffsetAndLength(this);
|
||||
copy.actualLength= getSize();
|
||||
return copy;
|
||||
}
|
||||
|
||||
public IASTInitializer [] getInitializers() {
|
||||
if( initializers == null ) return IASTInitializer.EMPTY_INITIALIZER_ARRAY;
|
||||
initializers = (IASTInitializer[]) ArrayUtil.removeNullsAfter( IASTInitializer.class, initializers, initializersPos );
|
||||
return initializers;
|
||||
}
|
||||
public int getSize() {
|
||||
return actualLength;
|
||||
}
|
||||
|
||||
public IASTInitializer[] getInitializers() {
|
||||
if (initializers == null)
|
||||
return IASTInitializer.EMPTY_INITIALIZER_ARRAY;
|
||||
|
||||
initializers = ArrayUtil.trimAt(IASTInitializer.class, initializers, initializersPos);
|
||||
return initializers;
|
||||
}
|
||||
|
||||
public void addInitializer( IASTInitializer d ) {
|
||||
assertNotFrozen();
|
||||
if (d != null) {
|
||||
initializers = (IASTInitializer[]) ArrayUtil.append( IASTInitializer.class, initializers, ++initializersPos, d );
|
||||
d.setParent(this);
|
||||
public void addInitializer(IASTInitializer d) {
|
||||
assertNotFrozen();
|
||||
if (d != null) {
|
||||
initializers = (IASTInitializer[]) ArrayUtil.append(IASTInitializer.class, initializers,
|
||||
++initializersPos, d);
|
||||
d.setParent(this);
|
||||
d.setPropertyInParent(NESTED_INITIALIZER);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private IASTInitializer [] initializers = null;
|
||||
private int initializersPos=-1;
|
||||
|
||||
}
|
||||
actualLength++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept( ASTVisitor action ){
|
||||
if( action.shouldVisitInitializers ){
|
||||
|
|
|
@ -603,17 +603,9 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
return throwExpression();
|
||||
}
|
||||
|
||||
// if (LT(1) == IToken.tLPAREN && LT(2) == IToken.tLBRACE
|
||||
// && supportStatementsInExpressions) {
|
||||
// IASTExpression resultExpression = compoundStatementExpression();
|
||||
// if (resultExpression != null)
|
||||
// return resultExpression;
|
||||
// }
|
||||
|
||||
// if this is a conditional expression, return right away.
|
||||
IASTExpression conditionalExpression = conditionalExpression();
|
||||
// if the condition not taken, try assignment operators
|
||||
if (conditionalExpression != null
|
||||
&& conditionalExpression instanceof IASTConditionalExpression) // &&
|
||||
if (conditionalExpression instanceof IASTConditionalExpression)
|
||||
return conditionalExpression;
|
||||
|
||||
switch (LT(1)) {
|
||||
|
@ -2609,10 +2601,10 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
|
|||
if (LT(1) == IToken.tRBRACE)
|
||||
break;
|
||||
|
||||
// clause may be null, add to initializer anyways, such that the
|
||||
// actual size can be computed.
|
||||
IASTInitializer clause = initializerClause(true);
|
||||
if (clause != null) {
|
||||
result.addInitializer(clause);
|
||||
}
|
||||
result.addInitializer(clause);
|
||||
if (LT(1) == IToken.tRBRACE || LT(1) == IToken.tEOC)
|
||||
break;
|
||||
consume(IToken.tCOMMA);
|
||||
|
|
|
@ -42,6 +42,7 @@ import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
|
|||
import org.eclipse.cdt.core.dom.ast.IASTImplicitNameOwner;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTInitializerExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTInitializerList;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTLabelStatement;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
|
||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||
|
@ -137,6 +138,7 @@ import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
|||
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.Value;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTranslationUnit;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPArrayType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
|
||||
|
@ -1638,26 +1640,34 @@ public class CPPVisitor extends ASTQueries {
|
|||
if (declarator == null)
|
||||
return null;
|
||||
|
||||
declarator= findOutermostDeclarator(declarator);
|
||||
IASTNode parent = declarator.getParent();
|
||||
|
||||
IASTDeclSpecifier declSpec = null;
|
||||
|
||||
IASTNode node = declarator.getParent();
|
||||
while (node instanceof IASTDeclarator) {
|
||||
declarator = (IASTDeclarator) node;
|
||||
node = node.getParent();
|
||||
}
|
||||
|
||||
if (node instanceof IASTParameterDeclaration) {
|
||||
declSpec = ((IASTParameterDeclaration) node).getDeclSpecifier();
|
||||
} else if (node instanceof IASTSimpleDeclaration) {
|
||||
declSpec = ((IASTSimpleDeclaration)node).getDeclSpecifier();
|
||||
} else if (node instanceof IASTFunctionDefinition) {
|
||||
declSpec = ((IASTFunctionDefinition)node).getDeclSpecifier();
|
||||
} else if (node instanceof IASTTypeId) {
|
||||
declSpec = ((IASTTypeId)node).getDeclSpecifier();
|
||||
if (parent instanceof IASTParameterDeclaration) {
|
||||
declSpec = ((IASTParameterDeclaration) parent).getDeclSpecifier();
|
||||
} else if (parent instanceof IASTSimpleDeclaration) {
|
||||
declSpec = ((IASTSimpleDeclaration)parent).getDeclSpecifier();
|
||||
} else if (parent instanceof IASTFunctionDefinition) {
|
||||
declSpec = ((IASTFunctionDefinition)parent).getDeclSpecifier();
|
||||
} else if (parent instanceof IASTTypeId) {
|
||||
declSpec = ((IASTTypeId)parent).getDeclSpecifier();
|
||||
}
|
||||
|
||||
IType type = createType(declSpec);
|
||||
type = createType(type, declarator);
|
||||
|
||||
// C++ specification 8.3.4.3 and 8.5.1.4
|
||||
IASTInitializer initializer= declarator.getInitializer();
|
||||
if (initializer instanceof IASTInitializerList) {
|
||||
IType t= SemanticUtil.getNestedType(type, TDEF);
|
||||
if (t instanceof IArrayType) {
|
||||
IArrayType at= (IArrayType) t;
|
||||
if (at.getSize() == null) {
|
||||
type= new CPPArrayType(at.getType(), Value.create(((IASTInitializerList) initializer).getSize()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue