1
0
Fork 0
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:
Markus Schorn 2008-10-31 10:06:53 +00:00
parent a831e865be
commit 10f412ae84
10 changed files with 304 additions and 189 deletions

View file

@ -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; }

View file

@ -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

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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;
}
}

View file

@ -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());
}
}

View file

@ -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();
}

View file

@ -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);

View file

@ -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);