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 { public void testCVQualifiersWithArrays_293982() throws Exception {
final String code = getAboveComment(); final String code = getAboveComment();
parseAndCheckBindings(code, ParserLanguage.CPP); 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. * 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. * @noextend This interface is not intended to be extended by clients.
* @noimplement This interface is not intended to be implemented 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$ "IASTInitializerList.NESTED_INITIALIZER - sub-IASTInitializer for IASTInitializerList"); //$NON-NLS-1$
/** /**
* Get the list 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()}.
* @return <code>IASTInitializer[]</code> array of initializers * @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(); public IASTInitializer[] getInitializers();
/** /**
* Add an initializer to the initializer list. * 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
* @param initializer * by {@link #getInitializers()}, however it contributes to the actual element count (#getSize()).
* <code>IASTInitializer</code>
*/ */
public void addInitializer(IASTInitializer initializer); public void addInitializer(IASTInitializer initializer);
/** /**
* @since 5.1 * @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 * 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
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
* *
* Contributors: * Contributors:
* IBM Rational Software - Initial API and implementation * John Camelon (IBM Rational Software) - Initial API and implementation
* Markus Schorn (Wind River Systems) * Markus Schorn (Wind River Systems)
* Yuan Zhang / Beth Tibbitts (IBM Research) * Yuan Zhang / Beth Tibbitts (IBM Research)
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.core.dom.parser.c; 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; 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 { public class CASTInitializerList extends ASTNode implements IASTInitializerList {
private IASTInitializer [] initializers = null;
private int initializersPos=-1;
private int actualSize;
public CASTInitializerList copy() { public CASTInitializerList copy() {
CASTInitializerList copy = new CASTInitializerList(); CASTInitializerList copy = new CASTInitializerList();
for(IASTInitializer initializer : getInitializers()) for(IASTInitializer initializer : getInitializers())
copy.addInitializer(initializer == null ? null : initializer.copy()); copy.addInitializer(initializer == null ? null : initializer.copy());
copy.setOffsetAndLength(this); copy.setOffsetAndLength(this);
copy.actualSize= getSize();
return copy; return copy;
} }
public IASTInitializer[] getInitializers() {
if( initializers == null ) return IASTInitializer.EMPTY_INITIALIZER_ARRAY; public int getSize() {
initializers = (IASTInitializer[]) ArrayUtil.removeNullsAfter( IASTInitializer.class, initializers, initializersPos ); return actualSize;
return initializers; }
}
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 ) { public void addInitializer( IASTInitializer d ) {
assertNotFrozen(); assertNotFrozen();
@ -44,10 +55,9 @@ public class CASTInitializerList extends ASTNode implements IASTInitializerList
d.setParent(this); d.setParent(this);
d.setPropertyInParent(NESTED_INITIALIZER); d.setPropertyInParent(NESTED_INITIALIZER);
} }
actualSize++;
} }
private IASTInitializer [] initializers = null;
private int initializersPos=-1;
@Override @Override
public boolean accept( ASTVisitor action ){ public boolean accept( ASTVisitor action ){

View file

@ -175,9 +175,8 @@ public class GNUCSourceParser extends AbstractGNUSourceCodeParser {
if (designator == null) { if (designator == null) {
IASTInitializer initializer= cInitializerClause(true); IASTInitializer initializer= cInitializerClause(true);
// depending on value of skipTrivialItemsInCompoundInitializers initializer may be null // depending on value of skipTrivialItemsInCompoundInitializers initializer may be null
if (initializer != null) { // in any way add the initializer such that the actual size can be tracked.
result.addInitializer(initializer); result.addInitializer(initializer);
}
} else { } else {
if (LT(1) == IToken.tASSIGN) if (LT(1) == IToken.tASSIGN)
consume(); 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 * 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
* http://www.eclipse.org/legal/epl-v10.html * http://www.eclipse.org/legal/epl-v10.html
* *
* Contributors: * 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; 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; 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 { public class CPPASTInitializerList extends ASTNode implements IASTInitializerList {
private IASTInitializer [] initializers = null;
private int initializersPos=-1;
private int actualLength;
public CPPASTInitializerList copy() { public CPPASTInitializerList copy() {
CPPASTInitializerList copy = new CPPASTInitializerList(); CPPASTInitializerList copy = new CPPASTInitializerList();
for(IASTInitializer initializer : getInitializers()) for(IASTInitializer initializer : getInitializers())
copy.addInitializer(initializer == null ? null : initializer.copy()); copy.addInitializer(initializer == null ? null : initializer.copy());
copy.setOffsetAndLength(this); copy.setOffsetAndLength(this);
copy.actualLength= getSize();
return copy; return copy;
} }
public IASTInitializer [] getInitializers() { public int getSize() {
if( initializers == null ) return IASTInitializer.EMPTY_INITIALIZER_ARRAY; return actualLength;
initializers = (IASTInitializer[]) ArrayUtil.removeNullsAfter( IASTInitializer.class, initializers, initializersPos ); }
return initializers;
} 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 ) { public void addInitializer(IASTInitializer d) {
assertNotFrozen(); assertNotFrozen();
if (d != null) { if (d != null) {
initializers = (IASTInitializer[]) ArrayUtil.append( IASTInitializer.class, initializers, ++initializersPos, d ); initializers = (IASTInitializer[]) ArrayUtil.append(IASTInitializer.class, initializers,
d.setParent(this); ++initializersPos, d);
d.setParent(this);
d.setPropertyInParent(NESTED_INITIALIZER); d.setPropertyInParent(NESTED_INITIALIZER);
} }
} actualLength++;
}
private IASTInitializer [] initializers = null;
private int initializersPos=-1;
@Override @Override
public boolean accept( ASTVisitor action ){ public boolean accept( ASTVisitor action ){
if( action.shouldVisitInitializers ){ if( action.shouldVisitInitializers ){

View file

@ -603,17 +603,9 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
return throwExpression(); return throwExpression();
} }
// if (LT(1) == IToken.tLPAREN && LT(2) == IToken.tLBRACE // if this is a conditional expression, return right away.
// && supportStatementsInExpressions) {
// IASTExpression resultExpression = compoundStatementExpression();
// if (resultExpression != null)
// return resultExpression;
// }
IASTExpression conditionalExpression = conditionalExpression(); IASTExpression conditionalExpression = conditionalExpression();
// if the condition not taken, try assignment operators if (conditionalExpression instanceof IASTConditionalExpression)
if (conditionalExpression != null
&& conditionalExpression instanceof IASTConditionalExpression) // &&
return conditionalExpression; return conditionalExpression;
switch (LT(1)) { switch (LT(1)) {
@ -2609,10 +2601,10 @@ public class GNUCPPSourceParser extends AbstractGNUSourceCodeParser {
if (LT(1) == IToken.tRBRACE) if (LT(1) == IToken.tRBRACE)
break; break;
// clause may be null, add to initializer anyways, such that the
// actual size can be computed.
IASTInitializer clause = initializerClause(true); IASTInitializer clause = initializerClause(true);
if (clause != null) { result.addInitializer(clause);
result.addInitializer(clause);
}
if (LT(1) == IToken.tRBRACE || LT(1) == IToken.tEOC) if (LT(1) == IToken.tRBRACE || LT(1) == IToken.tEOC)
break; break;
consume(IToken.tCOMMA); 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.IASTImplicitNameOwner;
import org.eclipse.cdt.core.dom.ast.IASTInitializer; import org.eclipse.cdt.core.dom.ast.IASTInitializer;
import org.eclipse.cdt.core.dom.ast.IASTInitializerExpression; 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.IASTLabelStatement;
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression; import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
import org.eclipse.cdt.core.dom.ast.IASTName; 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.ASTInternal;
import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; 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.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.CPPASTTranslationUnit;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPArrayType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPArrayType;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPBasicType;
@ -1638,26 +1640,34 @@ public class CPPVisitor extends ASTQueries {
if (declarator == null) if (declarator == null)
return null; return null;
declarator= findOutermostDeclarator(declarator);
IASTNode parent = declarator.getParent();
IASTDeclSpecifier declSpec = null; IASTDeclSpecifier declSpec = null;
if (parent instanceof IASTParameterDeclaration) {
IASTNode node = declarator.getParent(); declSpec = ((IASTParameterDeclaration) parent).getDeclSpecifier();
while (node instanceof IASTDeclarator) { } else if (parent instanceof IASTSimpleDeclaration) {
declarator = (IASTDeclarator) node; declSpec = ((IASTSimpleDeclaration)parent).getDeclSpecifier();
node = node.getParent(); } else if (parent instanceof IASTFunctionDefinition) {
} declSpec = ((IASTFunctionDefinition)parent).getDeclSpecifier();
} else if (parent instanceof IASTTypeId) {
if (node instanceof IASTParameterDeclaration) { declSpec = ((IASTTypeId)parent).getDeclSpecifier();
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();
} }
IType type = createType(declSpec); IType type = createType(declSpec);
type = createType(type, declarator); 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; return type;
} }