1
0
Fork 0
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:
Markus Schorn 2009-11-04 15:19:56 +00:00
parent fa2c3fcdd0
commit 8120ebe44f
7 changed files with 115 additions and 73 deletions

View file

@ -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);
}
}

View file

@ -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
*/

View file

@ -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 ){

View file

@ -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();

View file

@ -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 ){

View file

@ -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);

View file

@ -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;
}