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:
parent
450bef3a2c
commit
c5d05dd874
4 changed files with 119 additions and 38 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue