1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-23 22:52:11 +02:00

Consider all declarations of a variable for determining its type, bug 294144.

This commit is contained in:
Markus Schorn 2009-11-13 10:23:27 +00:00
parent 450bef3a2c
commit c5d05dd874
4 changed files with 119 additions and 38 deletions

View file

@ -7699,5 +7699,19 @@ public class AST2CPPTests extends AST2BaseTest {
final String code = getAboveComment();
parseAndCheckBindings(code, ParserLanguage.CPP);
}
// template <typename T, int N> char (&func(T (&array)[N]))[N];
// struct A {
// static int array[];
// };
// int A::array[] = { 0 };
//
// void test() {
// func(A::array); // func is not resolved
// }
public void testCompleteArrayTypeWithIncompleteDeclaration_294144() throws Exception {
final String code = getAboveComment();
parseAndCheckBindings(code, ParserLanguage.CPP);
}
}

View file

@ -23,6 +23,8 @@ import org.eclipse.cdt.core.dom.ast.IASTInitializerExpression;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IArrayType;
import org.eclipse.cdt.core.dom.ast.IBasicType;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IPointerType;
@ -88,9 +90,10 @@ public class CPPVariable extends PlatformObject implements ICPPVariable, ICPPInt
}
}
private IASTName declarations[] = null;
private IASTName definition = null;
private IType type = null;
private IASTName fDefinition = null;
private IASTName fDeclarations[] = null;
private IType fType = null;
private boolean fAllResolved;
public CPPVariable(IASTName name) {
boolean isDef = name == null ? false : name.isDefinition();
@ -100,9 +103,9 @@ public class CPPVariable extends PlatformObject implements ICPPVariable, ICPPInt
}
if (isDef)
definition = name;
fDefinition = name;
else
declarations = new IASTName[] { name };
fDeclarations = new IASTName[] { name };
// built-in variables supply a null
if (name != null) {
@ -131,54 +134,91 @@ public class CPPVariable extends PlatformObject implements ICPPVariable, ICPPInt
if (!(node instanceof IASTName))
return;
IASTName name = (IASTName) node;
if (name.isDefinition()) {
definition = name;
} else if (declarations == null) {
declarations = new IASTName[] { name };
} else {
//keep the lowest offset declaration in[0]
if (declarations.length > 0 && ((ASTNode) node).getOffset() < ((ASTNode) declarations[0]).getOffset()) {
declarations = (IASTName[]) ArrayUtil.prepend(IASTName.class, declarations, name);
if (fDefinition == null && name.isDefinition()) {
fDefinition = name;
} else if (fDeclarations == null) {
fDeclarations = new IASTName[] { name };
} else {
// keep the lowest offset declaration at the first position
if (fDeclarations.length > 0
&& ((ASTNode) node).getOffset() < ((ASTNode) fDeclarations[0]).getOffset()) {
fDeclarations = (IASTName[]) ArrayUtil.prepend(IASTName.class, fDeclarations, name);
} else {
declarations = (IASTName[]) ArrayUtil.append(IASTName.class, declarations, name);
fDeclarations = (IASTName[]) ArrayUtil.append(IASTName.class, fDeclarations, name);
}
}
}
// array types may be incomplete
if (fType instanceof IArrayType) {
fType = null;
}
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPBinding#getDeclarations()
*/
public IASTNode[] getDeclarations() {
return declarations;
return fDeclarations;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPBinding#getDefinition()
*/
public IASTNode getDefinition() {
return definition;
return fDefinition;
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IVariable#getType()
*/
public IType getType() {
if (type == null) {
IASTName n = null;
if (definition != null)
n = definition;
else if (declarations != null && declarations.length > 0)
n = declarations[0];
if (fType != null) {
return fType;
}
IArrayType firstCandidate= null;
final int length = fDeclarations == null ? 0 : fDeclarations.length;
for (int i = -1; i < length; i++) {
IASTName n = i==-1 ? fDefinition : fDeclarations[i];
if (n != null) {
while (n.getParent() instanceof IASTName)
n = (IASTName) n.getParent();
IASTNode node = n.getParent();
if (node instanceof IASTDeclarator)
type = CPPVisitor.createType((IASTDeclarator) node);
if (node instanceof IASTDeclarator) {
IType t= CPPVisitor.createType((IASTDeclarator) node);
if (t instanceof IArrayType && ((IArrayType) t).getSize() == null) {
if (firstCandidate == null) {
firstCandidate= (IArrayType) t;
}
} else {
return fType= t;
}
}
}
}
return type;
fType= firstCandidate;
if (!fAllResolved) {
resolveAllDeclarations();
return getType();
}
return fType;
}
private void resolveAllDeclarations() {
if (fAllResolved)
return;
fAllResolved= true;
final int length = fDeclarations == null ? 0 : fDeclarations.length;
for (int i = -1; i < length; i++) {
IASTName n = i==-1 ? fDefinition : fDeclarations[i];
if (n != null) {
IASTTranslationUnit tu = n.getTranslationUnit();
if (tu != null) {
CPPVisitor.getDeclarations(tu, this);
return;
}
}
}
}
/* (non-Javadoc)
@ -192,17 +232,17 @@ public class CPPVariable extends PlatformObject implements ICPPVariable, ICPPInt
* @see org.eclipse.cdt.core.dom.ast.IBinding#getNameCharArray()
*/
public char[] getNameCharArray() {
if (declarations != null) {
return declarations[0].getSimpleID();
if (fDeclarations != null) {
return fDeclarations[0].getSimpleID();
}
return definition.getSimpleID();
return fDefinition.getSimpleID();
}
/* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.IBinding#getScope()
*/
public IScope getScope() {
return CPPVisitor.getContainingScope(definition != null ? definition : declarations[0]);
return CPPVisitor.getContainingScope(fDefinition != null ? fDefinition : fDeclarations[0]);
}
/* (non-Javadoc)
@ -321,7 +361,7 @@ public class CPPVariable extends PlatformObject implements ICPPVariable, ICPPInt
}
public IBinding getOwner() throws DOMException {
IASTName node = definition != null ? definition : declarations[0];
IASTName node = fDefinition != null ? fDefinition : fDeclarations[0];
return CPPVisitor.findNameOwner(node, !hasStorageClass(IASTDeclSpecifier.sc_extern));
}
@ -335,13 +375,13 @@ public class CPPVariable extends PlatformObject implements ICPPVariable, ICPPInt
}
public IValue getInitialValue(int maxDepth) {
if (definition != null) {
final IValue val= getInitialValue(definition, maxDepth);
if (fDefinition != null) {
final IValue val= getInitialValue(fDefinition, maxDepth);
if (val != null)
return val;
}
if (declarations != null) {
for (IASTName decl : declarations) {
if (fDeclarations != null) {
for (IASTName decl : fDeclarations) {
if (decl == null)
break;
final IValue val= getInitialValue(decl, maxDepth);

View file

@ -32,6 +32,7 @@ import org.eclipse.cdt.core.dom.ast.EScopeKind;
import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression;
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
import org.eclipse.cdt.core.dom.ast.IASTCastExpression;
import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier;
import org.eclipse.cdt.core.dom.ast.IASTDeclaration;
@ -115,6 +116,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassTemplatePartialSpecialization;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPConstructor;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPField;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunction;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionTemplate;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType;
@ -282,6 +284,10 @@ public class CPPSemantics {
binding = e.getProblem();
}
}
if (binding instanceof IProblemBinding)
return binding;
if (binding == null && data.checkClassContainingFriend()) {
// 3.4.1-10 if we don't find a name used in a friend declaration in the member declaration's class
// we should look in the class granting friendship
@ -418,7 +424,7 @@ public class CPPSemantics {
}
}
if (binding != null && !(binding instanceof IProblemBinding)) {
if (binding != null) {
if (namePropertyInParent == IASTNamedTypeSpecifier.NAME) {
if (!(binding instanceof IType || binding instanceof ICPPConstructor)) {
IASTNode parent = name.getParent().getParent();
@ -452,7 +458,7 @@ public class CPPSemantics {
// explicit function specializations are found via name resolution, need to
// add name as definition and check the declaration specifier.
if (binding instanceof IFunction && !(binding instanceof IProblemBinding)) {
if (binding instanceof IFunction) {
if (data.forFunctionDeclaration()) {
IASTNode declaration= data.astName;
while (declaration instanceof IASTName)
@ -469,6 +475,19 @@ public class CPPSemantics {
}
}
// Definitions of static fields are found via name resolution, need to add name to
// the binding to get the right type of arrays that may be declared incomplete.
if (binding instanceof ICPPField && data.astName.isDefinition()) {
IASTNode declaration= data.astName;
while (declaration instanceof IASTName)
declaration= declaration.getParent();
while (declaration instanceof IASTDeclarator)
declaration= declaration.getParent();
if (declaration.getPropertyInParent() != IASTCompositeTypeSpecifier.MEMBER_DECLARATION) {
ASTInternal.addDefinition(binding, data.astName);
}
}
// If we're still null...
if (binding == null) {
if (name instanceof ICPPASTQualifiedName && data.forFunctionDeclaration()) {

View file

@ -1204,6 +1204,7 @@ public class CPPVisitor extends ASTQueries {
private IBinding[] bindings;
private int idx = 0;
private int kind;
private char[] requiredName;
private static final int KIND_LABEL = 1;
private static final int KIND_OBJ_FN = 2;
@ -1217,6 +1218,10 @@ public class CPPVisitor extends ASTQueries {
shouldVisitNames = true;
this.decls = new IASTName[DEFAULT_LIST_SIZE];
final String bname= binding.getName();
if (bname.length() > 0 && !bname.startsWith("operator")) { //$NON-NLS-1$
requiredName= bname.toCharArray();
}
this.bindings = new IBinding[] {binding};
if (binding instanceof ICPPUsingDeclaration) {
this.bindings= ((ICPPUsingDeclaration) binding).getDelegates();
@ -1240,6 +1245,9 @@ public class CPPVisitor extends ASTQueries {
@Override
public int visit(IASTName name) {
if (name instanceof ICPPASTQualifiedName) return PROCESS_CONTINUE;
if (requiredName != null && !CharArrayUtils.equals(name.getLookupKey(), requiredName)) {
return PROCESS_CONTINUE;
}
ASTNodeProperty prop = name.getPropertyInParent();
if (prop == ICPPASTQualifiedName.SEGMENT_NAME)