From 8120ebe44f2d7a5f7e827e0873ba000966d36a39 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Wed, 4 Nov 2009 15:19:56 +0000 Subject: [PATCH] Array size determined by initializer expression, bug 294144. --- .../core/parser/tests/ast2/AST2CPPTests.java | 17 ++++++- .../cdt/core/dom/ast/IASTInitializerList.java | 23 ++++++--- .../dom/parser/c/CASTInitializerList.java | 34 ++++++++----- .../core/dom/parser/c/GNUCSourceParser.java | 5 +- .../dom/parser/cpp/CPPASTInitializerList.java | 51 +++++++++++-------- .../dom/parser/cpp/GNUCPPSourceParser.java | 18 ++----- .../dom/parser/cpp/semantics/CPPVisitor.java | 40 +++++++++------ 7 files changed, 115 insertions(+), 73 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java index 3d5562f052f..fb1ffb6482d 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2CPPTests.java @@ -7672,6 +7672,21 @@ public class AST2CPPTests extends AST2BaseTest { public void testCVQualifiersWithArrays_293982() throws Exception { final String code = getAboveComment(); parseAndCheckBindings(code, ParserLanguage.CPP); - } + } + + // template 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); + } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTInitializerList.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTInitializerList.java index 6559181ec5f..937ab4c8aab 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTInitializerList.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/core/dom/ast/IASTInitializerList.java @@ -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: + *
 int a[]= {1,2,3}; 
* * @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 IASTInitializer[] 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 - * IASTInitializer + * Add an initializer to the initializer list. Depending on how the AST is created the + * initializer may be null. A null 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 */ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTInitializerList.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTInitializerList.java index 806abe0e1b4..86c7a0a839e 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTInitializerList.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTInitializerList.java @@ -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 ){ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java index 35e5b9a08bc..0726b07b192 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/GNUCSourceParser.java @@ -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(); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTInitializerList.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTInitializerList.java index 24cead27102..125b8e1f196 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTInitializerList.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTInitializerList.java @@ -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 ){ diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java index f0618f83784..a0ae60987ed 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/GNUCPPSourceParser.java @@ -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); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java index c6f3ff72fe1..09a9f836d4d 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/semantics/CPPVisitor.java @@ -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; }