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.parser.ParserLanguage;
|
||||
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.OverloadableOperator;
|
||||
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 {
|
||||
// also tests bug 234042.
|
||||
boolean old= CPPASTName.fAllowRecursionBindings;
|
||||
CPPASTName.fAllowRecursionBindings= false;
|
||||
try {
|
||||
IASTTranslationUnit tu = parse(getAboveComment(), ParserLanguage.CPP);
|
||||
CPPNameCollector col = new CPPNameCollector();
|
||||
tu.accept(col);
|
||||
AbstractCPPASTName.sAllowRecursionBindings= false;
|
||||
|
||||
assertEquals(col.size(), 9);
|
||||
IASTTranslationUnit tu = parse(getAboveComment(), ParserLanguage.CPP);
|
||||
CPPNameCollector col = new CPPNameCollector();
|
||||
tu.accept(col);
|
||||
|
||||
ICPPClassType Node = (ICPPClassType) col.getName(1).resolveBinding();
|
||||
ICPPClassType Data = (ICPPClassType) col.getName(3).resolveBinding();
|
||||
assertSame(Data.getScope(), tu.getScope());
|
||||
assertEquals(col.size(), 9);
|
||||
|
||||
assertInstances(col, Node, 3);
|
||||
assertInstances(col, Data, 2);
|
||||
}
|
||||
finally {
|
||||
CPPASTName.fAllowRecursionBindings= old;
|
||||
}
|
||||
ICPPClassType Node = (ICPPClassType) col.getName(1).resolveBinding();
|
||||
ICPPClassType Data = (ICPPClassType) col.getName(3).resolveBinding();
|
||||
assertSame(Data.getScope(), tu.getScope());
|
||||
|
||||
assertInstances(col, Node, 3);
|
||||
assertInstances(col, Data, 2);
|
||||
}
|
||||
|
||||
// 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.IElementChangedListener;
|
||||
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.ILogListener;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
|
@ -56,6 +57,7 @@ public class BaseTestCase extends TestCase {
|
|||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
AbstractCPPASTName.sAllowRecursionBindings= true;
|
||||
}
|
||||
|
||||
@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
|
||||
*
|
||||
* Contributors:
|
||||
* IBM - Initial API and implementation
|
||||
* John Camelon(IBM) - Initial API and implementation
|
||||
* Markus Schorn (Wind River Systems)
|
||||
* Bryan Wilkinson (QNX)
|
||||
* 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.IBinding;
|
||||
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.ICPPClassType;
|
||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace;
|
||||
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.parser.ASTNode;
|
||||
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.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 {
|
||||
/**
|
||||
* 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;
|
||||
|
||||
public class CPPASTName extends AbstractCPPASTName implements IASTCompletionContext {
|
||||
private char[] name;
|
||||
private IBinding binding = null;
|
||||
private int fResolutionDepth= 0;
|
||||
|
||||
public CPPASTName(char[] name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public CPPASTName() {
|
||||
name = EMPTY_CHAR_ARRAY;
|
||||
name = CharArrayUtils.EMPTY;
|
||||
}
|
||||
|
||||
public IBinding resolveBinding() {
|
||||
if (binding == null) {
|
||||
if (++fResolutionDepth > MAX_RESOLUTION_DEPTH) {
|
||||
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);
|
||||
}
|
||||
@Override
|
||||
protected IBinding createIntermediateBinding() {
|
||||
return CPPVisitor.createBinding(this);
|
||||
}
|
||||
|
||||
public IASTCompletionContext getCompletionContext() {
|
||||
|
@ -164,19 +129,10 @@ public class CPPASTName extends ASTNode implements IASTName, IASTCompletionConte
|
|||
return (IBinding[])ArrayUtil.removeNulls(IBinding.class, bindings);
|
||||
}
|
||||
|
||||
public void setBinding(IBinding binding) {
|
||||
this.binding = binding;
|
||||
fResolutionDepth= 0;
|
||||
}
|
||||
|
||||
public IBinding getBinding() {
|
||||
return binding;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (name == EMPTY_CHAR_ARRAY)
|
||||
return EMPTY_STRING;
|
||||
if (name.length == 0)
|
||||
return ""; //$NON-NLS-1$
|
||||
return new String(name);
|
||||
}
|
||||
|
||||
|
@ -275,8 +231,4 @@ public class CPPASTName extends ASTNode implements IASTName, IASTCompletionConte
|
|||
public ILinkage getLinkage() {
|
||||
return Linkage.CPP_LINKAGE;
|
||||
}
|
||||
|
||||
public IASTName getLastName() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* IBM - Initial API and implementation
|
||||
* John Camelon (IBM) - Initial API and implementation
|
||||
* Bryan Wilkinson (QNX)
|
||||
* 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.CharArrayUtils;
|
||||
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.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
|
||||
ICPPASTQualifiedName, IASTCompletionContext {
|
||||
public class CPPASTQualifiedName extends AbstractCPPASTName
|
||||
implements ICPPASTQualifiedName, IASTCompletionContext {
|
||||
|
||||
private IASTName[] names = null;
|
||||
private int namesPos= -1;
|
||||
private boolean isFullyQualified;
|
||||
private String signature;
|
||||
|
||||
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() {
|
||||
// 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();
|
||||
}
|
||||
|
||||
@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() {
|
||||
IASTNode node = getParent();
|
||||
while (node != null) {
|
||||
|
@ -75,6 +103,7 @@ public class CPPASTQualifiedName extends ASTNode implements
|
|||
}
|
||||
|
||||
public void addName(IASTName name) {
|
||||
assert !(name instanceof ICPPASTQualifiedName);
|
||||
if (name != null) {
|
||||
names = (IASTName[]) ArrayUtil.append(IASTName.class, names, ++namesPos, name);
|
||||
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() {
|
||||
if (names == null)
|
||||
if (namesPos < 0)
|
||||
return IASTName.EMPTY_NAME_ARRAY;
|
||||
removeNullNames();
|
||||
|
||||
names = (IASTName[]) ArrayUtil.removeNullsAfter(IASTName.class, names, namesPos);
|
||||
return names;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IASTName getLastName() {
|
||||
if (namesPos < 0)
|
||||
return null;
|
||||
|
@ -107,31 +128,29 @@ public class CPPASTQualifiedName extends ASTNode implements
|
|||
}
|
||||
|
||||
public char[] toCharArray() {
|
||||
if (names == null)
|
||||
if (namesPos < 0)
|
||||
return new char[0];
|
||||
removeNullNames();
|
||||
|
||||
// count first
|
||||
int len = 0;
|
||||
for (int i = 0; i < names.length; ++i) {
|
||||
int len = -2;
|
||||
for (int i = 0; i <= namesPos; ++i) {
|
||||
char[] n = names[i].toCharArray();
|
||||
if (n == null)
|
||||
return null;
|
||||
len += n.length;
|
||||
if (i != names.length - 1)
|
||||
len += 2;
|
||||
len+= 2;
|
||||
len+= n.length;
|
||||
}
|
||||
|
||||
char[] nameArray = new char[len];
|
||||
int pos = 0;
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
char[] n = names[i].toCharArray();
|
||||
System.arraycopy(n, 0, nameArray, pos, n.length);
|
||||
pos += n.length;
|
||||
if (i != names.length - 1) {
|
||||
for (int i = 0; i <= namesPos; i++) {
|
||||
if (i != 0) {
|
||||
nameArray[pos++] = ':';
|
||||
nameArray[pos++] = ':';
|
||||
}
|
||||
final char[] n = names[i].toCharArray();
|
||||
System.arraycopy(n, 0, nameArray, pos, n.length);
|
||||
pos += n.length;
|
||||
}
|
||||
return nameArray;
|
||||
}
|
||||
|
@ -161,9 +180,8 @@ public class CPPASTQualifiedName extends ASTNode implements
|
|||
break;
|
||||
}
|
||||
}
|
||||
IASTName[] ns = getNames();
|
||||
for (int i = 0; i < ns.length; i++) {
|
||||
if (i == names.length - 1) {
|
||||
for (int i = 0; i <= namesPos; i++) {
|
||||
if (i == namesPos) {
|
||||
// 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))
|
||||
return false;
|
||||
|
@ -217,41 +235,28 @@ public class CPPASTQualifiedName extends ASTNode implements
|
|||
}
|
||||
|
||||
public int getRoleForName(IASTName n) {
|
||||
IASTName[] namez = getNames();
|
||||
for(int i = 0; i < names.length; ++i)
|
||||
if (namez[i] == n)
|
||||
{
|
||||
if (i < names.length - 1)
|
||||
return r_reference;
|
||||
IASTNode p = getParent();
|
||||
if (i == names.length - 1 && p instanceof IASTNameOwner)
|
||||
return ((IASTNameOwner)p).getRoleForName(this);
|
||||
return r_unclear;
|
||||
for (int i=0; i < namesPos; ++i) {
|
||||
if (names[i] == n)
|
||||
return r_reference;
|
||||
}
|
||||
if (getLastName() == n) {
|
||||
IASTNode p = getParent();
|
||||
if (p instanceof IASTNameOwner) {
|
||||
return ((IASTNameOwner)p).getRoleForName(this);
|
||||
}
|
||||
}
|
||||
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() {
|
||||
IASTName[] nonNullNames = getNames(); // ensure no null names
|
||||
|
||||
int len=nonNullNames.length;
|
||||
if (nonNullNames[len - 1] instanceof ICPPASTConversionName || nonNullNames[len - 1] instanceof ICPPASTOperatorName) {
|
||||
final IASTName lastName= getLastName();
|
||||
if (lastName instanceof ICPPASTConversionName || lastName instanceof ICPPASTOperatorName) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// check templateId's name
|
||||
if (nonNullNames[len - 1] instanceof ICPPASTTemplateId) {
|
||||
IASTName tempName = ((ICPPASTTemplateId)nonNullNames[len - 1]).getTemplateName();
|
||||
if (lastName instanceof ICPPASTTemplateId) {
|
||||
IASTName tempName = ((ICPPASTTemplateId)lastName).getTemplateName();
|
||||
if (tempName instanceof ICPPASTConversionName || tempName instanceof ICPPASTOperatorName) {
|
||||
return true;
|
||||
}
|
||||
|
@ -273,8 +278,8 @@ public class CPPASTQualifiedName extends ASTNode implements
|
|||
public IBinding[] findBindings(IASTName n, boolean isPrefix) {
|
||||
IBinding[] bindings = CPPSemantics.findBindingsForContentAssist(n, isPrefix);
|
||||
|
||||
if (names.length - 2 >= 0) {
|
||||
IBinding binding = names[names.length - 2].resolveBinding();
|
||||
if (namesPos > 0) {
|
||||
IBinding binding = names[namesPos-1].resolveBinding();
|
||||
if (binding instanceof ICPPClassType) {
|
||||
ICPPClassType classType = (ICPPClassType) binding;
|
||||
final boolean isDeclaration = getParent().getParent() instanceof IASTSimpleDeclaration;
|
||||
|
@ -344,4 +349,10 @@ public class CPPASTQualifiedName extends ASTNode implements
|
|||
public ILinkage getLinkage() {
|
||||
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
|
||||
*
|
||||
* Contributors:
|
||||
* IBM - Initial API and implementation
|
||||
* John Camelon (IBM) - Initial API and implementation
|
||||
* Markus Schorn (Wind River Systems)
|
||||
* 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.IBinding;
|
||||
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.parser.util.ArrayUtil;
|
||||
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.IASTInternalNameOwner;
|
||||
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 IASTNode[] templateArguments = null;
|
||||
private IBinding binding = null;
|
||||
private int fResolutionDepth = 0;
|
||||
|
||||
public CPPASTTemplateId() {
|
||||
}
|
||||
|
||||
|
@ -51,6 +49,7 @@ public class CPPASTTemplateId extends ASTNode implements ICPPASTTemplateId, IAST
|
|||
}
|
||||
|
||||
public void setTemplateName(IASTName name) {
|
||||
assert !(name instanceof ICPPASTQualifiedName) && !(name instanceof ICPPASTTemplateId);
|
||||
templateName = name;
|
||||
if (name != null) {
|
||||
name.setParent(this);
|
||||
|
@ -87,17 +86,9 @@ public class CPPASTTemplateId extends ASTNode implements ICPPASTTemplateId, IAST
|
|||
return (IASTNode[]) ArrayUtil.trim(IASTNode.class, templateArguments);
|
||||
}
|
||||
|
||||
public IBinding resolveBinding() {
|
||||
if (binding == null) {
|
||||
// protect for infinite recursion
|
||||
if (++fResolutionDepth > CPPASTName.MAX_RESOLUTION_DEPTH) {
|
||||
binding= new CPPASTName.RecursionResolvingBinding(this);
|
||||
} else {
|
||||
binding = CPPTemplates.createBinding(this);
|
||||
}
|
||||
}
|
||||
|
||||
return binding;
|
||||
@Override
|
||||
protected IBinding createIntermediateBinding() {
|
||||
return CPPTemplates.createBinding(this);
|
||||
}
|
||||
|
||||
public IASTCompletionContext getCompletionContext() {
|
||||
|
@ -152,15 +143,6 @@ public class CPPASTTemplateId extends ASTNode implements ICPPASTTemplateId, IAST
|
|||
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) {
|
||||
if (templateArguments == null) return;
|
||||
for (int i = 0; i < templateArguments.length; ++i) {
|
||||
|
@ -192,17 +174,7 @@ public class CPPASTTemplateId extends ASTNode implements ICPPASTTemplateId, IAST
|
|||
return false;
|
||||
}
|
||||
|
||||
public void incResolutionDepth() {
|
||||
if (binding == null && ++fResolutionDepth > CPPASTName.MAX_RESOLUTION_DEPTH) {
|
||||
binding = new CPPASTName.RecursionResolvingBinding(this);
|
||||
}
|
||||
}
|
||||
|
||||
public ILinkage getLinkage() {
|
||||
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 {
|
||||
public RecursionResolvingBinding(IASTNode node, char[] 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.ProblemBinding;
|
||||
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.CPPASTIdExpression;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTName;
|
||||
|
@ -174,6 +175,10 @@ public class CPPSemantics {
|
|||
if (traceBindingResolution) {
|
||||
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
|
||||
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.ITypeContainer;
|
||||
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.CPPBasicType;
|
||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPClassTemplate;
|
||||
|
@ -1033,16 +1031,7 @@ public class CPPVisitor {
|
|||
}
|
||||
}
|
||||
if (name != null) {
|
||||
if (name instanceof ICPPASTQualifiedName) {
|
||||
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();
|
||||
}
|
||||
name= name.getLastName();
|
||||
IBinding binding = name.getBinding();
|
||||
if (binding == null) {
|
||||
binding = CPPSemantics.resolveBinding(name);
|
||||
|
|
Loading…
Add table
Reference in a new issue