mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Mechanism to resolve bindings in two phases, bug 252554.
This commit is contained in:
parent
a831e865be
commit
10f412ae84
10 changed files with 304 additions and 189 deletions
|
@ -111,7 +111,7 @@ import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPPointerToMemberType;
|
||||||
import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPPointerType;
|
import org.eclipse.cdt.core.dom.ast.gnu.cpp.IGPPPointerType;
|
||||||
import org.eclipse.cdt.core.parser.ParserLanguage;
|
import org.eclipse.cdt.core.parser.ParserLanguage;
|
||||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.AbstractCPPASTName;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.OverloadableOperator;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
|
||||||
|
@ -1671,25 +1671,20 @@ public class AST2CPPTests extends AST2BaseTest {
|
||||||
// };
|
// };
|
||||||
public void testBug84692() throws Exception {
|
public void testBug84692() throws Exception {
|
||||||
// also tests bug 234042.
|
// also tests bug 234042.
|
||||||
boolean old= CPPASTName.fAllowRecursionBindings;
|
AbstractCPPASTName.sAllowRecursionBindings= false;
|
||||||
CPPASTName.fAllowRecursionBindings= false;
|
|
||||||
try {
|
|
||||||
IASTTranslationUnit tu = parse(getAboveComment(), ParserLanguage.CPP);
|
|
||||||
CPPNameCollector col = new CPPNameCollector();
|
|
||||||
tu.accept(col);
|
|
||||||
|
|
||||||
assertEquals(col.size(), 9);
|
IASTTranslationUnit tu = parse(getAboveComment(), ParserLanguage.CPP);
|
||||||
|
CPPNameCollector col = new CPPNameCollector();
|
||||||
|
tu.accept(col);
|
||||||
|
|
||||||
ICPPClassType Node = (ICPPClassType) col.getName(1).resolveBinding();
|
assertEquals(col.size(), 9);
|
||||||
ICPPClassType Data = (ICPPClassType) col.getName(3).resolveBinding();
|
|
||||||
assertSame(Data.getScope(), tu.getScope());
|
|
||||||
|
|
||||||
assertInstances(col, Node, 3);
|
ICPPClassType Node = (ICPPClassType) col.getName(1).resolveBinding();
|
||||||
assertInstances(col, Data, 2);
|
ICPPClassType Data = (ICPPClassType) col.getName(3).resolveBinding();
|
||||||
}
|
assertSame(Data.getScope(), tu.getScope());
|
||||||
finally {
|
|
||||||
CPPASTName.fAllowRecursionBindings= old;
|
assertInstances(col, Node, 3);
|
||||||
}
|
assertInstances(col, Data, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// namespace B { int b; }
|
// namespace B { int b; }
|
||||||
|
|
|
@ -32,6 +32,7 @@ import org.eclipse.cdt.core.model.CoreModel;
|
||||||
import org.eclipse.cdt.core.model.ElementChangedEvent;
|
import org.eclipse.cdt.core.model.ElementChangedEvent;
|
||||||
import org.eclipse.cdt.core.model.IElementChangedListener;
|
import org.eclipse.cdt.core.model.IElementChangedListener;
|
||||||
import org.eclipse.cdt.core.testplugin.TestScannerProvider;
|
import org.eclipse.cdt.core.testplugin.TestScannerProvider;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.AbstractCPPASTName;
|
||||||
import org.eclipse.core.runtime.CoreException;
|
import org.eclipse.core.runtime.CoreException;
|
||||||
import org.eclipse.core.runtime.ILogListener;
|
import org.eclipse.core.runtime.ILogListener;
|
||||||
import org.eclipse.core.runtime.IProgressMonitor;
|
import org.eclipse.core.runtime.IProgressMonitor;
|
||||||
|
@ -56,6 +57,7 @@ public class BaseTestCase extends TestCase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setUp() throws Exception {
|
protected void setUp() throws Exception {
|
||||||
|
AbstractCPPASTName.sAllowRecursionBindings= true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,153 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2008 Wind River Systems, Inc. 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:
|
||||||
|
* Markus Schorn - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
|
||||||
|
import org.eclipse.core.runtime.Assert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common base class for all sorts of c++ names: unqualified, qualified, operator and conversion
|
||||||
|
* names plus template-ids
|
||||||
|
*/
|
||||||
|
public abstract class AbstractCPPASTName extends ASTNode implements IASTName {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For test-purposes, only.
|
||||||
|
*/
|
||||||
|
public static boolean sAllowRecursionBindings = true;
|
||||||
|
private static final byte MAX_RESOLUTION_DEPTH= 6;
|
||||||
|
|
||||||
|
protected final static class RecursionResolvingBinding extends ProblemBinding {
|
||||||
|
public RecursionResolvingBinding(IASTName node) {
|
||||||
|
super(node, IProblemBinding.SEMANTIC_RECURSION_IN_LOOKUP, node.toCharArray());
|
||||||
|
Assert.isTrue(sAllowRecursionBindings, getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to resolve intermediate bindings without casting the name.
|
||||||
|
*/
|
||||||
|
public static IBinding resolveIntermediateBinding(IASTName name) {
|
||||||
|
if (name == null)
|
||||||
|
return null;
|
||||||
|
if (name instanceof AbstractCPPASTName)
|
||||||
|
return ((AbstractCPPASTName) name).resolveIntermediateBinding();
|
||||||
|
return name.resolveBinding();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper method to get intermediate bindings without casting the name.
|
||||||
|
*/
|
||||||
|
public static IBinding getIntermediateBinding(IASTName name) {
|
||||||
|
if (name == null)
|
||||||
|
return null;
|
||||||
|
if (name instanceof AbstractCPPASTName)
|
||||||
|
return ((AbstractCPPASTName) name).getIntermediateBinding();
|
||||||
|
return name.resolveBinding();
|
||||||
|
}
|
||||||
|
|
||||||
|
private IBinding fBinding = null;
|
||||||
|
private byte fResolutionDepth = 0;
|
||||||
|
private boolean fIsFinal= false;
|
||||||
|
|
||||||
|
public final void incResolutionDepth() {
|
||||||
|
if (fBinding == null && ++fResolutionDepth > MAX_RESOLUTION_DEPTH) {
|
||||||
|
fBinding = new RecursionResolvingBinding(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called to perform the binding resolution. Subclasses may return lazy bindings that
|
||||||
|
* will not be exposed within public API.
|
||||||
|
*/
|
||||||
|
protected abstract IBinding createIntermediateBinding();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the name at least up to the intermediate binding and returns it.
|
||||||
|
* @see ICPPTwoPhaseBinding
|
||||||
|
*/
|
||||||
|
public IBinding resolveIntermediateBinding() {
|
||||||
|
if (fBinding == null) {
|
||||||
|
if (++fResolutionDepth > MAX_RESOLUTION_DEPTH) {
|
||||||
|
fBinding= new RecursionResolvingBinding(this);
|
||||||
|
} else {
|
||||||
|
fBinding= createIntermediateBinding();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fBinding;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IBinding resolveBinding() {
|
||||||
|
if (fBinding == null) {
|
||||||
|
if (++fResolutionDepth > MAX_RESOLUTION_DEPTH) {
|
||||||
|
fBinding= new RecursionResolvingBinding(this);
|
||||||
|
} else {
|
||||||
|
fBinding= createIntermediateBinding();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!fIsFinal)
|
||||||
|
resolveFinalBinding();
|
||||||
|
|
||||||
|
return fBinding;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this name has not yet been resolved at all, <code>null</code> will be returned.
|
||||||
|
* Otherwise the intermediate or final binding for this name is returned.
|
||||||
|
* @see ICPPTwoPhaseBinding
|
||||||
|
*/
|
||||||
|
public IBinding getIntermediateBinding() {
|
||||||
|
final IBinding cand= fBinding;
|
||||||
|
if (cand == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
return fBinding;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IBinding getBinding() {
|
||||||
|
final IBinding cand= fBinding;
|
||||||
|
if (cand == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (!fIsFinal)
|
||||||
|
resolveFinalBinding();
|
||||||
|
|
||||||
|
return fBinding;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resolveFinalBinding() {
|
||||||
|
if (fBinding instanceof ICPPTwoPhaseBinding) {
|
||||||
|
ICPPTwoPhaseBinding lazyBinding= (ICPPTwoPhaseBinding) fBinding;
|
||||||
|
if (++fResolutionDepth > MAX_RESOLUTION_DEPTH) {
|
||||||
|
fBinding= new RecursionResolvingBinding(this);
|
||||||
|
} else {
|
||||||
|
IBinding finalBinding= lazyBinding.resolveFinalBinding();
|
||||||
|
assert finalBinding.getClass().equals(lazyBinding.getClass());
|
||||||
|
|
||||||
|
fBinding= finalBinding;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fIsFinal= true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBinding(IBinding binding) {
|
||||||
|
fBinding= binding;
|
||||||
|
fResolutionDepth= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IASTName getLastName() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,7 +6,7 @@
|
||||||
* 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)
|
* Markus Schorn (Wind River Systems)
|
||||||
* Bryan Wilkinson (QNX)
|
* Bryan Wilkinson (QNX)
|
||||||
* Anton Leherbauer (Wind River Systems)
|
* Anton Leherbauer (Wind River Systems)
|
||||||
|
@ -24,67 +24,32 @@ import org.eclipse.cdt.core.dom.ast.IASTNameOwner;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||||
import org.eclipse.cdt.core.dom.ast.ICompositeType;
|
import org.eclipse.cdt.core.dom.ast.ICompositeType;
|
||||||
import org.eclipse.cdt.core.dom.ast.IProblemBinding;
|
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTElaboratedTypeSpecifier;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
|
||||||
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||||
|
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||||
import org.eclipse.cdt.internal.core.dom.Linkage;
|
import org.eclipse.cdt.internal.core.dom.Linkage;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.IASTInternalNameOwner;
|
import org.eclipse.cdt.internal.core.dom.parser.IASTInternalNameOwner;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
|
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor;
|
||||||
import org.eclipse.core.runtime.Assert;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author jcamelon
|
* Unqualified name, also base class for operator and conversion name.
|
||||||
*/
|
*/
|
||||||
public class CPPASTName extends ASTNode implements IASTName, IASTCompletionContext {
|
public class CPPASTName extends AbstractCPPASTName implements IASTCompletionContext {
|
||||||
/**
|
|
||||||
* For test-purposes, only.
|
|
||||||
*/
|
|
||||||
public static boolean fAllowRecursionBindings= true;
|
|
||||||
|
|
||||||
final static class RecursionResolvingBinding extends ProblemBinding {
|
|
||||||
public RecursionResolvingBinding(IASTName node) {
|
|
||||||
super(node, IProblemBinding.SEMANTIC_RECURSION_IN_LOOKUP, node.toCharArray());
|
|
||||||
Assert.isTrue(fAllowRecursionBindings, getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final char[] EMPTY_CHAR_ARRAY = {};
|
|
||||||
private static final String EMPTY_STRING = ""; //$NON-NLS-1$
|
|
||||||
|
|
||||||
static final int MAX_RESOLUTION_DEPTH = 5;
|
|
||||||
|
|
||||||
private char[] name;
|
private char[] name;
|
||||||
private IBinding binding = null;
|
|
||||||
private int fResolutionDepth= 0;
|
|
||||||
|
|
||||||
public CPPASTName(char[] name) {
|
public CPPASTName(char[] name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CPPASTName() {
|
public CPPASTName() {
|
||||||
name = EMPTY_CHAR_ARRAY;
|
name = CharArrayUtils.EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IBinding resolveBinding() {
|
@Override
|
||||||
if (binding == null) {
|
protected IBinding createIntermediateBinding() {
|
||||||
if (++fResolutionDepth > MAX_RESOLUTION_DEPTH) {
|
return CPPVisitor.createBinding(this);
|
||||||
binding = new RecursionResolvingBinding(this);
|
|
||||||
} else {
|
|
||||||
binding = CPPVisitor.createBinding(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return binding;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void incResolutionDepth() {
|
|
||||||
if (binding == null && ++fResolutionDepth > MAX_RESOLUTION_DEPTH) {
|
|
||||||
binding = new RecursionResolvingBinding(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IASTCompletionContext getCompletionContext() {
|
public IASTCompletionContext getCompletionContext() {
|
||||||
|
@ -164,19 +129,10 @@ public class CPPASTName extends ASTNode implements IASTName, IASTCompletionConte
|
||||||
return (IBinding[])ArrayUtil.removeNulls(IBinding.class, bindings);
|
return (IBinding[])ArrayUtil.removeNulls(IBinding.class, bindings);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBinding(IBinding binding) {
|
|
||||||
this.binding = binding;
|
|
||||||
fResolutionDepth= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IBinding getBinding() {
|
|
||||||
return binding;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
if (name == EMPTY_CHAR_ARRAY)
|
if (name.length == 0)
|
||||||
return EMPTY_STRING;
|
return ""; //$NON-NLS-1$
|
||||||
return new String(name);
|
return new String(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,8 +231,4 @@ public class CPPASTName extends ASTNode implements IASTName, IASTCompletionConte
|
||||||
public ILinkage getLinkage() {
|
public ILinkage getLinkage() {
|
||||||
return Linkage.CPP_LINKAGE;
|
return Linkage.CPP_LINKAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IASTName getLastName() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* 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
|
||||||
* Bryan Wilkinson (QNX)
|
* Bryan Wilkinson (QNX)
|
||||||
* Markus Schorn (Wind River Systems)
|
* Markus Schorn (Wind River Systems)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -37,26 +37,54 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod;
|
||||||
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||||
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
import org.eclipse.cdt.core.parser.util.CharArrayUtils;
|
||||||
import org.eclipse.cdt.internal.core.dom.Linkage;
|
import org.eclipse.cdt.internal.core.dom.Linkage;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.IASTInternalNameOwner;
|
import org.eclipse.cdt.internal.core.dom.parser.IASTInternalNameOwner;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics;
|
||||||
|
import org.eclipse.core.runtime.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author jcamelon
|
* Qualified name, which can contain any other name (unqualified, operator-name, conversion name,
|
||||||
|
* template id).
|
||||||
*/
|
*/
|
||||||
public class CPPASTQualifiedName extends ASTNode implements
|
public class CPPASTQualifiedName extends AbstractCPPASTName
|
||||||
ICPPASTQualifiedName, IASTCompletionContext {
|
implements ICPPASTQualifiedName, IASTCompletionContext {
|
||||||
|
|
||||||
|
private IASTName[] names = null;
|
||||||
|
private int namesPos= -1;
|
||||||
|
private boolean isFullyQualified;
|
||||||
|
private String signature;
|
||||||
|
|
||||||
public CPPASTQualifiedName() {
|
public CPPASTQualifiedName() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final IBinding resolveIntermediateBinding() {
|
||||||
|
// The full qualified name resolves to the same thing as the last name
|
||||||
|
return resolveIntermediateBinding(getLastName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public IBinding resolveBinding() {
|
public IBinding resolveBinding() {
|
||||||
// The full qualified name resolves to the same thing as the last name
|
// The full qualified name resolves to the same thing as the last name
|
||||||
removeNullNames();
|
IASTName lastName= getLastName();
|
||||||
IASTName lastName = getLastName();
|
|
||||||
return lastName == null ? null : lastName.resolveBinding();
|
return lastName == null ? null : lastName.resolveBinding();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final IBinding getIntermediateBinding() {
|
||||||
|
// The full qualified name resolves to the same thing as the last name
|
||||||
|
return getIntermediateBinding(getLastName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBinding getBinding() {
|
||||||
|
return getLastName().getBinding();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBinding(IBinding binding) {
|
||||||
|
getLastName().setBinding(binding);
|
||||||
|
}
|
||||||
|
|
||||||
public IASTCompletionContext getCompletionContext() {
|
public IASTCompletionContext getCompletionContext() {
|
||||||
IASTNode node = getParent();
|
IASTNode node = getParent();
|
||||||
while (node != null) {
|
while (node != null) {
|
||||||
|
@ -75,6 +103,7 @@ public class CPPASTQualifiedName extends ASTNode implements
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addName(IASTName name) {
|
public void addName(IASTName name) {
|
||||||
|
assert !(name instanceof ICPPASTQualifiedName);
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
names = (IASTName[]) ArrayUtil.append(IASTName.class, names, ++namesPos, name);
|
names = (IASTName[]) ArrayUtil.append(IASTName.class, names, ++namesPos, name);
|
||||||
name.setParent(this);
|
name.setParent(this);
|
||||||
|
@ -82,23 +111,15 @@ public class CPPASTQualifiedName extends ASTNode implements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeNullNames() {
|
|
||||||
names = (IASTName[]) ArrayUtil.removeNullsAfter(IASTName.class, names, namesPos);
|
|
||||||
}
|
|
||||||
|
|
||||||
private IASTName[] names = null;
|
|
||||||
private int namesPos= -1;
|
|
||||||
private boolean isFullyQualified;
|
|
||||||
private String signature;
|
|
||||||
|
|
||||||
|
|
||||||
public IASTName[] getNames() {
|
public IASTName[] getNames() {
|
||||||
if (names == null)
|
if (namesPos < 0)
|
||||||
return IASTName.EMPTY_NAME_ARRAY;
|
return IASTName.EMPTY_NAME_ARRAY;
|
||||||
removeNullNames();
|
|
||||||
|
names = (IASTName[]) ArrayUtil.removeNullsAfter(IASTName.class, names, namesPos);
|
||||||
return names;
|
return names;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public IASTName getLastName() {
|
public IASTName getLastName() {
|
||||||
if (namesPos < 0)
|
if (namesPos < 0)
|
||||||
return null;
|
return null;
|
||||||
|
@ -107,31 +128,29 @@ public class CPPASTQualifiedName extends ASTNode implements
|
||||||
}
|
}
|
||||||
|
|
||||||
public char[] toCharArray() {
|
public char[] toCharArray() {
|
||||||
if (names == null)
|
if (namesPos < 0)
|
||||||
return new char[0];
|
return new char[0];
|
||||||
removeNullNames();
|
|
||||||
|
|
||||||
// count first
|
// count first
|
||||||
int len = 0;
|
int len = -2;
|
||||||
for (int i = 0; i < names.length; ++i) {
|
for (int i = 0; i <= namesPos; ++i) {
|
||||||
char[] n = names[i].toCharArray();
|
char[] n = names[i].toCharArray();
|
||||||
if (n == null)
|
if (n == null)
|
||||||
return null;
|
return null;
|
||||||
len += n.length;
|
len+= 2;
|
||||||
if (i != names.length - 1)
|
len+= n.length;
|
||||||
len += 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char[] nameArray = new char[len];
|
char[] nameArray = new char[len];
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
for (int i = 0; i < names.length; i++) {
|
for (int i = 0; i <= namesPos; i++) {
|
||||||
char[] n = names[i].toCharArray();
|
if (i != 0) {
|
||||||
System.arraycopy(n, 0, nameArray, pos, n.length);
|
|
||||||
pos += n.length;
|
|
||||||
if (i != names.length - 1) {
|
|
||||||
nameArray[pos++] = ':';
|
nameArray[pos++] = ':';
|
||||||
nameArray[pos++] = ':';
|
nameArray[pos++] = ':';
|
||||||
}
|
}
|
||||||
|
final char[] n = names[i].toCharArray();
|
||||||
|
System.arraycopy(n, 0, nameArray, pos, n.length);
|
||||||
|
pos += n.length;
|
||||||
}
|
}
|
||||||
return nameArray;
|
return nameArray;
|
||||||
}
|
}
|
||||||
|
@ -161,9 +180,8 @@ public class CPPASTQualifiedName extends ASTNode implements
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IASTName[] ns = getNames();
|
for (int i = 0; i <= namesPos; i++) {
|
||||||
for (int i = 0; i < ns.length; i++) {
|
if (i == namesPos) {
|
||||||
if (i == names.length - 1) {
|
|
||||||
// pointer-to-member qualified names have a dummy name as the last part of the name, don't visit it
|
// pointer-to-member qualified names have a dummy name as the last part of the name, don't visit it
|
||||||
if (names[i].toCharArray().length > 0 && !names[i].accept(action))
|
if (names[i].toCharArray().length > 0 && !names[i].accept(action))
|
||||||
return false;
|
return false;
|
||||||
|
@ -217,41 +235,28 @@ public class CPPASTQualifiedName extends ASTNode implements
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getRoleForName(IASTName n) {
|
public int getRoleForName(IASTName n) {
|
||||||
IASTName[] namez = getNames();
|
for (int i=0; i < namesPos; ++i) {
|
||||||
for(int i = 0; i < names.length; ++i)
|
if (names[i] == n)
|
||||||
if (namez[i] == n)
|
return r_reference;
|
||||||
{
|
}
|
||||||
if (i < names.length - 1)
|
if (getLastName() == n) {
|
||||||
return r_reference;
|
IASTNode p = getParent();
|
||||||
IASTNode p = getParent();
|
if (p instanceof IASTNameOwner) {
|
||||||
if (i == names.length - 1 && p instanceof IASTNameOwner)
|
return ((IASTNameOwner)p).getRoleForName(this);
|
||||||
return ((IASTNameOwner)p).getRoleForName(this);
|
|
||||||
return r_unclear;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return r_unclear;
|
return r_unclear;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IBinding getBinding() {
|
|
||||||
removeNullNames();
|
|
||||||
return names[names.length - 1].getBinding();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBinding(IBinding binding) {
|
|
||||||
removeNullNames();
|
|
||||||
names[names.length - 1].setBinding(binding);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isConversionOrOperator() {
|
public boolean isConversionOrOperator() {
|
||||||
IASTName[] nonNullNames = getNames(); // ensure no null names
|
final IASTName lastName= getLastName();
|
||||||
|
if (lastName instanceof ICPPASTConversionName || lastName instanceof ICPPASTOperatorName) {
|
||||||
int len=nonNullNames.length;
|
|
||||||
if (nonNullNames[len - 1] instanceof ICPPASTConversionName || nonNullNames[len - 1] instanceof ICPPASTOperatorName) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// check templateId's name
|
// check templateId's name
|
||||||
if (nonNullNames[len - 1] instanceof ICPPASTTemplateId) {
|
if (lastName instanceof ICPPASTTemplateId) {
|
||||||
IASTName tempName = ((ICPPASTTemplateId)nonNullNames[len - 1]).getTemplateName();
|
IASTName tempName = ((ICPPASTTemplateId)lastName).getTemplateName();
|
||||||
if (tempName instanceof ICPPASTConversionName || tempName instanceof ICPPASTOperatorName) {
|
if (tempName instanceof ICPPASTConversionName || tempName instanceof ICPPASTOperatorName) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -273,8 +278,8 @@ public class CPPASTQualifiedName extends ASTNode implements
|
||||||
public IBinding[] findBindings(IASTName n, boolean isPrefix) {
|
public IBinding[] findBindings(IASTName n, boolean isPrefix) {
|
||||||
IBinding[] bindings = CPPSemantics.findBindingsForContentAssist(n, isPrefix);
|
IBinding[] bindings = CPPSemantics.findBindingsForContentAssist(n, isPrefix);
|
||||||
|
|
||||||
if (names.length - 2 >= 0) {
|
if (namesPos > 0) {
|
||||||
IBinding binding = names[names.length - 2].resolveBinding();
|
IBinding binding = names[namesPos-1].resolveBinding();
|
||||||
if (binding instanceof ICPPClassType) {
|
if (binding instanceof ICPPClassType) {
|
||||||
ICPPClassType classType = (ICPPClassType) binding;
|
ICPPClassType classType = (ICPPClassType) binding;
|
||||||
final boolean isDeclaration = getParent().getParent() instanceof IASTSimpleDeclaration;
|
final boolean isDeclaration = getParent().getParent() instanceof IASTSimpleDeclaration;
|
||||||
|
@ -344,4 +349,10 @@ public class CPPASTQualifiedName extends ASTNode implements
|
||||||
public ILinkage getLinkage() {
|
public ILinkage getLinkage() {
|
||||||
return Linkage.CPP_LINKAGE;
|
return Linkage.CPP_LINKAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected IBinding createIntermediateBinding() {
|
||||||
|
Assert.isLegal(false);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
* 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)
|
* Markus Schorn (Wind River Systems)
|
||||||
* Andrew Ferguson (Symbian)
|
* Andrew Ferguson (Symbian)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
|
@ -22,23 +22,21 @@ import org.eclipse.cdt.core.dom.ast.IASTNode;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
|
import org.eclipse.cdt.core.dom.ast.IASTTypeId;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTAmbiguousTemplateArgument;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTAmbiguousTemplateArgument;
|
||||||
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
|
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTTemplateId;
|
||||||
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
import org.eclipse.cdt.core.parser.util.ArrayUtil;
|
||||||
import org.eclipse.cdt.internal.core.dom.Linkage;
|
import org.eclipse.cdt.internal.core.dom.Linkage;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
|
import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguityParent;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.IASTInternalNameOwner;
|
import org.eclipse.cdt.internal.core.dom.parser.IASTInternalNameOwner;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPTemplates;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author jcamelon
|
* Template ids consist of an unqualified name (or operator or conversion name)
|
||||||
|
* and an array of template arguments.
|
||||||
*/
|
*/
|
||||||
public class CPPASTTemplateId extends ASTNode implements ICPPASTTemplateId, IASTAmbiguityParent {
|
public class CPPASTTemplateId extends AbstractCPPASTName implements ICPPASTTemplateId, IASTAmbiguityParent {
|
||||||
private IASTName templateName;
|
private IASTName templateName;
|
||||||
private IASTNode[] templateArguments = null;
|
private IASTNode[] templateArguments = null;
|
||||||
private IBinding binding = null;
|
|
||||||
private int fResolutionDepth = 0;
|
|
||||||
|
|
||||||
public CPPASTTemplateId() {
|
public CPPASTTemplateId() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,6 +49,7 @@ public class CPPASTTemplateId extends ASTNode implements ICPPASTTemplateId, IAST
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTemplateName(IASTName name) {
|
public void setTemplateName(IASTName name) {
|
||||||
|
assert !(name instanceof ICPPASTQualifiedName) && !(name instanceof ICPPASTTemplateId);
|
||||||
templateName = name;
|
templateName = name;
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
name.setParent(this);
|
name.setParent(this);
|
||||||
|
@ -87,17 +86,9 @@ public class CPPASTTemplateId extends ASTNode implements ICPPASTTemplateId, IAST
|
||||||
return (IASTNode[]) ArrayUtil.trim(IASTNode.class, templateArguments);
|
return (IASTNode[]) ArrayUtil.trim(IASTNode.class, templateArguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IBinding resolveBinding() {
|
@Override
|
||||||
if (binding == null) {
|
protected IBinding createIntermediateBinding() {
|
||||||
// protect for infinite recursion
|
return CPPTemplates.createBinding(this);
|
||||||
if (++fResolutionDepth > CPPASTName.MAX_RESOLUTION_DEPTH) {
|
|
||||||
binding= new CPPASTName.RecursionResolvingBinding(this);
|
|
||||||
} else {
|
|
||||||
binding = CPPTemplates.createBinding(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return binding;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public IASTCompletionContext getCompletionContext() {
|
public IASTCompletionContext getCompletionContext() {
|
||||||
|
@ -152,15 +143,6 @@ public class CPPASTTemplateId extends ASTNode implements ICPPASTTemplateId, IAST
|
||||||
return r_unclear;
|
return r_unclear;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IBinding getBinding() {
|
|
||||||
return binding;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBinding(IBinding binding) {
|
|
||||||
this.binding = binding;
|
|
||||||
fResolutionDepth = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void replace(IASTNode child, IASTNode other) {
|
public void replace(IASTNode child, IASTNode other) {
|
||||||
if (templateArguments == null) return;
|
if (templateArguments == null) return;
|
||||||
for (int i = 0; i < templateArguments.length; ++i) {
|
for (int i = 0; i < templateArguments.length; ++i) {
|
||||||
|
@ -192,17 +174,7 @@ public class CPPASTTemplateId extends ASTNode implements ICPPASTTemplateId, IAST
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void incResolutionDepth() {
|
|
||||||
if (binding == null && ++fResolutionDepth > CPPASTName.MAX_RESOLUTION_DEPTH) {
|
|
||||||
binding = new CPPASTName.RecursionResolvingBinding(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ILinkage getLinkage() {
|
public ILinkage getLinkage() {
|
||||||
return Linkage.CPP_LINKAGE;
|
return Linkage.CPP_LINKAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IASTName getLastName() {
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ public class CPPTypedefSpecialization extends CPPSpecialization implements IType
|
||||||
final static class RecursionResolvingBinding extends ProblemBinding {
|
final static class RecursionResolvingBinding extends ProblemBinding {
|
||||||
public RecursionResolvingBinding(IASTNode node, char[] arg) {
|
public RecursionResolvingBinding(IASTNode node, char[] arg) {
|
||||||
super(node, IProblemBinding.SEMANTIC_RECURSION_IN_LOOKUP, arg);
|
super(node, IProblemBinding.SEMANTIC_RECURSION_IN_LOOKUP, arg);
|
||||||
Assert.isTrue(CPPASTName.fAllowRecursionBindings, getMessage());
|
Assert.isTrue(CPPASTName.sAllowRecursionBindings, getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*******************************************************************************
|
||||||
|
* Copyright (c) 2008 Wind River Systems, Inc. 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:
|
||||||
|
* Markus Schorn - initial API and implementation
|
||||||
|
*******************************************************************************/
|
||||||
|
package org.eclipse.cdt.internal.core.dom.parser.cpp;
|
||||||
|
|
||||||
|
import org.eclipse.cdt.core.dom.ast.IBinding;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface for bindings that are resolvable in two steps. The binding computed
|
||||||
|
* by the first step is an intermediate binding that can be replaced in a second
|
||||||
|
* step before the binding is exposed via public API.
|
||||||
|
* <p>
|
||||||
|
* The bindings of the two phases may not be equal, but they must have the <b> same type</b>.
|
||||||
|
* <p>
|
||||||
|
* This allows for having multiple bindings for one final binding and deferring
|
||||||
|
* the act of unifying them to a later point in time.
|
||||||
|
*/
|
||||||
|
public interface ICPPTwoPhaseBinding extends IBinding {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers the second step of the resolution where the binding that will be
|
||||||
|
* exposed via public API has to be computed. If this binding is already final
|
||||||
|
* {@code this} must be returned.
|
||||||
|
* <p> Note, that the result of this operation is an instance of
|
||||||
|
* {@link ICPPTwoPhaseBinding}, however it must resolve to itself using
|
||||||
|
* {@link #resolveFinalBinding()}.
|
||||||
|
*/
|
||||||
|
ICPPTwoPhaseBinding resolveFinalBinding();
|
||||||
|
}
|
|
@ -133,6 +133,7 @@ import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.IASTInternalScope;
|
import org.eclipse.cdt.internal.core.dom.parser.IASTInternalScope;
|
||||||
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.Value;
|
||||||
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.AbstractCPPASTName;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFieldReference;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTFieldReference;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTIdExpression;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTIdExpression;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName;
|
||||||
|
@ -174,6 +175,10 @@ public class CPPSemantics {
|
||||||
if (traceBindingResolution) {
|
if (traceBindingResolution) {
|
||||||
System.out.println("Resolving " + name); //$NON-NLS-1$
|
System.out.println("Resolving " + name); //$NON-NLS-1$
|
||||||
}
|
}
|
||||||
|
if (name instanceof AbstractCPPASTName) {
|
||||||
|
((AbstractCPPASTName) name).incResolutionDepth();
|
||||||
|
}
|
||||||
|
|
||||||
// 1: get some context info off of the name to figure out what kind of lookup we want
|
// 1: get some context info off of the name to figure out what kind of lookup we want
|
||||||
LookupData data = createLookupData(name, true);
|
LookupData data = createLookupData(name, true);
|
||||||
|
|
||||||
|
|
|
@ -147,8 +147,6 @@ 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.ITypeContainer;
|
import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
|
||||||
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.cpp.CPPASTName;
|
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTTemplateId;
|
|
||||||
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;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassTemplate;
|
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassTemplate;
|
||||||
|
@ -1033,16 +1031,7 @@ public class CPPVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
if (name instanceof ICPPASTQualifiedName) {
|
name= name.getLastName();
|
||||||
IASTName ns[] = ((ICPPASTQualifiedName)name).getNames();
|
|
||||||
name = ns[ns.length - 1];
|
|
||||||
}
|
|
||||||
if (name instanceof CPPASTName) {
|
|
||||||
((CPPASTName) name).incResolutionDepth();
|
|
||||||
}
|
|
||||||
else if (name instanceof CPPASTTemplateId) {
|
|
||||||
((CPPASTTemplateId) name).incResolutionDepth();
|
|
||||||
}
|
|
||||||
IBinding binding = name.getBinding();
|
IBinding binding = name.getBinding();
|
||||||
if (binding == null) {
|
if (binding == null) {
|
||||||
binding = CPPSemantics.resolveBinding(name);
|
binding = CPPSemantics.resolveBinding(name);
|
||||||
|
|
Loading…
Add table
Reference in a new issue