From 939ab1508d4896bc6792e05efd048681bdfe85d2 Mon Sep 17 00:00:00 2001 From: Markus Schorn Date: Mon, 31 Oct 2011 17:05:55 +0100 Subject: [PATCH] Bug 360541: Ambiguity resolution for declaration statements. --- .../cdt/core/parser/tests/ast2/AST2Tests.java | 17 ++++- .../core/dom/parser/ASTAmbiguousNode.java | 6 +- .../core/dom/parser/IASTInternalScope.java | 7 ++ .../core/dom/parser/ProblemBinding.java | 58 +++++++++++---- .../dom/parser/c/CASTAmbiguityResolver.java | 3 - .../dom/parser/c/CASTAmbiguousStatement.java | 45 ++++++++++-- .../internal/core/dom/parser/c/CScope.java | 73 ++++++++++++++++--- .../parser/cpp/CPPASTAmbiguityResolver.java | 3 - .../parser/cpp/CPPASTAmbiguousStatement.java | 47 ++++++++++-- .../cpp/CPPClassSpecializationScope.java | 6 ++ .../core/dom/parser/cpp/CPPScope.java | 54 +++++++++++++- .../core/dom/parser/cpp/CPPUnknownScope.java | 33 +++++++-- .../dom/lrparser/c99/bindings/C99Scope.java | 3 + 13 files changed, 297 insertions(+), 58 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java index c6392ba67ef..a1744313ddb 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/AST2Tests.java @@ -138,7 +138,13 @@ public class AST2Tests extends AST2BaseTest { public AST2Tests(String name) { super(name); } - + + private void parseAndCheckBindings() throws Exception { + String code= getAboveComment(); + parseAndCheckBindings(code, ParserLanguage.C); + parseAndCheckBindings(code, ParserLanguage.CPP); + } + protected IASTTranslationUnit parseAndCheckBindings(String code) throws Exception { return parseAndCheckBindings(code, ParserLanguage.C); } @@ -7360,4 +7366,13 @@ public class AST2Tests extends AST2BaseTest { es= getStatement(a, 2); assertEquals("unsigned long int", ASTTypeUtil.getType(es.getExpression().getExpressionType())); } + + // void foo(){ + // typedef int foobar_t; + // foobar_t *a = 0, *b = a; + // } + public void testAmbiguousStatement_Bug360541() throws Exception { + parseAndCheckBindings(); + } + } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTAmbiguousNode.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTAmbiguousNode.java index 9ab1ba8dc78..772fd3e70c8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTAmbiguousNode.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ASTAmbiguousNode.java @@ -83,12 +83,12 @@ public abstract class ASTAmbiguousNode extends ASTNode { int minIssues = Integer.MAX_VALUE; for (IASTNode alternative : alternatives) { - beforeAlternative(alternative); - - // setup the ast to use the alternative + // Setup the ast to use the alternative owner.replace(nodeToReplace, alternative); nodeToReplace= alternative; + beforeAlternative(alternative); + // handle nested ambiguities first, otherwise we cannot visit the alternative alternative.accept(resolver); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/IASTInternalScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/IASTInternalScope.java index 1cb20611cc2..e347d0c22bc 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/IASTInternalScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/IASTInternalScope.java @@ -41,4 +41,11 @@ public interface IASTInternalScope extends IScope { * the ambiguities have been resolved. */ public void populateCache(); + + /** + * Can be called during ambiguity resolution to remove the names within the given + * node from the cache. + */ + public void removeNestedFromCache(IASTNode container); + } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemBinding.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemBinding.java index 00750fe2a31..b63128ee0a4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemBinding.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/ProblemBinding.java @@ -68,14 +68,17 @@ public class ProblemBinding extends PlatformObject implements IProblemBinding, I this.candidateBindings = candidateBindings; } + @Override public EScopeKind getKind() { return EScopeKind.eLocal; } - public IASTNode getASTNode() { + @Override + public IASTNode getASTNode() { return node; } + @Override public IBinding[] getCandidateBindings() { return candidateBindings != null ? candidateBindings : IBinding.EMPTY_BINDING_ARRAY; } @@ -87,14 +90,16 @@ public class ProblemBinding extends PlatformObject implements IProblemBinding, I /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IProblemBinding#getID() */ - public int getID() { + @Override + public int getID() { return id; } /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IProblemBinding#getMessage() */ - public String getMessage() { + @Override + public String getMessage() { if (message != null) return message; @@ -115,28 +120,32 @@ public class ProblemBinding extends PlatformObject implements IProblemBinding, I /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IBinding#getName() */ - public String getName() { + @Override + public String getName() { return node instanceof IASTName ? new String(((IASTName) node).getSimpleID()) : CPPSemantics.EMPTY_NAME; } /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IBinding#getNameCharArray() */ - public char[] getNameCharArray() { + @Override + public char[] getNameCharArray() { return node instanceof IASTName ? ((IASTName) node).getSimpleID() : CharArrayUtils.EMPTY; } /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IBinding#getScope() */ - public IScope getScope() throws DOMException { + @Override + public IScope getScope() throws DOMException { throw new DOMException(this); } /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IBinding#getPhysicalNode() */ - public IASTNode getPhysicalNode() { + @Override + public IASTNode getPhysicalNode() { return getASTNode(); } @@ -150,20 +159,23 @@ public class ProblemBinding extends PlatformObject implements IProblemBinding, I /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IScope#getParent() */ - public IScope getParent() throws DOMException { + @Override + public IScope getParent() throws DOMException { throw new DOMException(this); } /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IScope#find(java.lang.String) */ - public IBinding[] find(String name) { + @Override + public IBinding[] find(String name) { return IBinding.EMPTY_BINDING_ARRAY; } /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IScope#getScopeName() */ + @Override public IName getScopeName() { return null; } @@ -171,16 +183,19 @@ public class ProblemBinding extends PlatformObject implements IProblemBinding, I /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IScope#addName(org.eclipse.cdt.core.dom.ast.IASTName) */ - public void addName(IASTName name) { + @Override + public void addName(IASTName name) { } /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IScope#getBinding(org.eclipse.cdt.core.dom.ast.IASTName, boolean) */ - public IBinding getBinding(IASTName name, boolean resolve) { + @Override + public IBinding getBinding(IASTName name, boolean resolve) { return null; } + @Override public final IBinding[] getBindings(IASTName name, boolean resolve, boolean prefix) { return IBinding.EMPTY_BINDING_ARRAY; } @@ -188,24 +203,28 @@ public class ProblemBinding extends PlatformObject implements IProblemBinding, I /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IScope#getBinding(org.eclipse.cdt.core.dom.ast.IASTName, boolean) */ - public IBinding getBinding(IASTName name, boolean resolve, IIndexFileSet fileSet) { + @Override + public IBinding getBinding(IASTName name, boolean resolve, IIndexFileSet fileSet) { return null; } /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IScope#getBinding(org.eclipse.cdt.core.dom.ast.IASTName, boolean) */ - public IBinding[] getBindings(IASTName name, boolean resolve, boolean prefixLookup, IIndexFileSet fileSet) { + @Override + public IBinding[] getBindings(IASTName name, boolean resolve, boolean prefixLookup, IIndexFileSet fileSet) { return IBinding.EMPTY_BINDING_ARRAY; } /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IType#isSameType(org.eclipse.cdt.core.dom.ast.IType) */ - public boolean isSameType(IType type) { + @Override + public boolean isSameType(IType type) { return type == this; } + @Override public String getFileName() { if (node != null) return node.getContainingFilename(); @@ -213,6 +232,7 @@ public class ProblemBinding extends PlatformObject implements IProblemBinding, I return ""; //$NON-NLS-1$ } + @Override public int getLineNumber() { if (node != null) { IASTFileLocation fileLoc = node.getFileLocation(); @@ -222,9 +242,11 @@ public class ProblemBinding extends PlatformObject implements IProblemBinding, I return -1; } + @Override public void addBinding(IBinding binding) { } + @Override public ILinkage getLinkage() { return Linkage.NO_LINKAGE; } @@ -234,6 +256,7 @@ public class ProblemBinding extends PlatformObject implements IProblemBinding, I return getMessage(); } + @Override public IBinding getOwner() { if (node instanceof IASTName) { IASTTranslationUnit tu= node.getTranslationUnit(); @@ -251,10 +274,13 @@ public class ProblemBinding extends PlatformObject implements IProblemBinding, I } } + @Override public void populateCache() { } - - + + @Override + public void removeNestedFromCache(IASTNode container) {} + // Dummy methods for derived classes public IType getType() { return new ProblemType(getID()); diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTAmbiguityResolver.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTAmbiguityResolver.java index eddda75e797..41de90e46a5 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTAmbiguityResolver.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTAmbiguityResolver.java @@ -12,7 +12,6 @@ package org.eclipse.cdt.internal.core.dom.parser.c; import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTDeclaration; -import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement; import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTNode; @@ -47,8 +46,6 @@ public final class CASTAmbiguityResolver extends ASTVisitor { } node= node.getParent(); } - } else if (node instanceof IASTDeclarationStatement) { - repopulateScope(((IASTDeclarationStatement) node).getDeclaration()); } return PROCESS_SKIP; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTAmbiguousStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTAmbiguousStatement.java index 0a62bc6d06b..6bc13e2de8f 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTAmbiguousStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CASTAmbiguousStatement.java @@ -11,6 +11,9 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.c; +import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.IASTDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTStatement; import org.eclipse.cdt.core.dom.ast.IScope; @@ -18,11 +21,14 @@ import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousNode; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousStatement; import org.eclipse.cdt.internal.core.dom.parser.IASTInternalScope; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPASTInternalScope; public class CASTAmbiguousStatement extends ASTAmbiguousNode implements IASTAmbiguousStatement { private IASTStatement [] stmts = new IASTStatement[2]; private int stmtsPos=-1; + private IScope fScope; + private IASTDeclaration fDeclaration; public CASTAmbiguousStatement(IASTStatement... statements) { for(IASTStatement s : statements) @@ -31,13 +37,39 @@ public class CASTAmbiguousStatement extends ASTAmbiguousNode implements IASTAmbi @Override protected void beforeResolution() { - // populate containing scope, so that it will not be affected by the alternative branches. - IScope scope= CVisitor.getContainingScope(this); - if (scope instanceof IASTInternalScope) { - ((IASTInternalScope) scope).populateCache(); + // Populate containing scope, so that it will not be affected by the alternative + // branches. + fScope= CVisitor.getContainingScope(this); + if (fScope instanceof ICPPASTInternalScope) { + ((ICPPASTInternalScope) fScope).populateCache(); + } + } + + @Override + protected void beforeAlternative(IASTNode alternative) { + cleanupScope(); + if (alternative instanceof IASTDeclarationStatement) { + if (fScope instanceof CScope) { + fDeclaration = ((IASTDeclarationStatement) alternative).getDeclaration(); + ((CScope) fScope).collectNames(fDeclaration); + } + } + } + + private void cleanupScope() { + if (fScope instanceof IASTInternalScope && fDeclaration != null) { + ((IASTInternalScope) fScope).removeNestedFromCache(fDeclaration); } } + @Override + protected void afterResolution(ASTVisitor resolver, IASTNode best) { + beforeAlternative(best); + fDeclaration= null; + fScope= null; + } + + @Override public void addStatement(IASTStatement s) { assertNotFrozen(); if (s != null) { @@ -47,7 +79,8 @@ public class CASTAmbiguousStatement extends ASTAmbiguousNode implements IASTAmbi } } - public IASTStatement[] getStatements() { + @Override + public IASTStatement[] getStatements() { stmts = (IASTStatement[]) ArrayUtil.removeNullsAfter( IASTStatement.class, stmts, stmtsPos ); return stmts; } @@ -58,10 +91,12 @@ public class CASTAmbiguousStatement extends ASTAmbiguousNode implements IASTAmbi } + @Override public IASTStatement copy() { throw new UnsupportedOperationException(); } + @Override public IASTStatement copy(CopyStyle style) { throw new UnsupportedOperationException(); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CScope.java index fa1fcfd8516..4e9b526a4b6 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CScope.java @@ -112,7 +112,7 @@ public class CScope implements ICScope, IASTInternalScope { private IASTNode physicalNode = null; private boolean isCached = false; - private CharArrayObjectMap[] mapsToNameOrBinding = { CharArrayObjectMap.EMPTY_MAP, CharArrayObjectMap.EMPTY_MAP }; + private CharArrayObjectMap mapsToNameOrBinding[] = { CharArrayObjectMap.EMPTY_MAP, CharArrayObjectMap.EMPTY_MAP }; private final EScopeKind kind; public CScope(IASTNode physical, EScopeKind eKind) { @@ -120,6 +120,7 @@ public class CScope implements ICScope, IASTInternalScope { kind= eKind; } + @Override public EScopeKind getKind() { return kind; } @@ -127,7 +128,8 @@ public class CScope implements ICScope, IASTInternalScope { /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IScope#getParent() */ - public IScope getParent() { + @Override + public IScope getParent() { return CVisitor.getContainingScope(physicalNode); } @@ -167,6 +169,7 @@ public class CScope implements ICScope, IASTInternalScope { /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IScope#find(java.lang.String) */ + @Override public IBinding[] find(String name) { return CVisitor.findBindings(this, name); } @@ -188,19 +191,22 @@ public class CScope implements ICScope, IASTInternalScope { /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IScope#getPhysicalNode() */ - public IASTNode getPhysicalNode() { + @Override + public IASTNode getPhysicalNode() { return physicalNode; } + @Override public void addName(IASTName name) { final char[] nchars = name.toCharArray(); if (nchars.length == 0) return; int type = getNamespaceType(name); - CharArrayObjectMap map = mapsToNameOrBinding[type]; + @SuppressWarnings("unchecked") + CharArrayObjectMap map = (CharArrayObjectMap) mapsToNameOrBinding[type]; if (map == CharArrayObjectMap.EMPTY_MAP) - map = mapsToNameOrBinding[type] = new CharArrayObjectMap(1); + mapsToNameOrBinding[type] = map = new CharArrayObjectMap(1); Object o= map.get(nchars); if (o instanceof IASTName) { @@ -234,14 +240,17 @@ public class CScope implements ICScope, IASTInternalScope { return NAMESPACE_TYPE_OTHER; } - public final IBinding getBinding(IASTName name, boolean resolve) { + @Override + public final IBinding getBinding(IASTName name, boolean resolve) { return getBinding(name, resolve, IIndexFileSet.EMPTY); } + @Override public final IBinding[] getBindings(IASTName name, boolean resolve, boolean prefix) { return getBindings(name, resolve, prefix, IIndexFileSet.EMPTY); } + @Override public final IBinding getBinding(IASTName name, boolean resolve, IIndexFileSet fileSet) { char[] c = name.toCharArray(); if (c.length == 0) { @@ -323,12 +332,13 @@ public class CScope implements ICScope, IASTInternalScope { /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.c.ICScope#getBinding(org.eclipse.cdt.core.dom.ast.IASTName, boolean) */ + @Override public final IBinding[] getBindings(IASTName name, boolean resolve, boolean prefixLookup, IIndexFileSet fileSet) { char[] c = name.toCharArray(); Object[] obj = null; populateCache(); - for (CharArrayObjectMap map : mapsToNameOrBinding) { + for (CharArrayObjectMap map : mapsToNameOrBinding) { if (prefixLookup) { IContentAssistMatcher matcher = ContentAssistMatcherFactory.getInstance().createMatcher(c); Object[] keys = map.keyArray(); @@ -405,7 +415,8 @@ public class CScope implements ICScope, IASTInternalScope { return bindings[0]; } - public void populateCache() { + @Override + public void populateCache() { if (isCached) return; @@ -413,6 +424,45 @@ public class CScope implements ICScope, IASTInternalScope { isCached= true; } + @Override + public void removeNestedFromCache(IASTNode container) { + if (mapsToNameOrBinding != null) { + removeFromMap(mapsToNameOrBinding[0], container); + removeFromMap(mapsToNameOrBinding[1], container); + } + } + + private void removeFromMap(CharArrayObjectMap map, IASTNode container) { + for (int i = 0; i < map.size(); i++) { + Object o= map.getAt(i); + if (o instanceof IASTName) { + if (container.contains((IASTNode) o)) { + final char[] key = map.keyAt(i); + map.remove(key, 0, key.length); + i--; + } + } else if (o instanceof IASTName[]) { + final IASTName[] set = (IASTName[]) o; + removeFromSet(set, container); + } + } + } + + private void removeFromSet(IASTName[] set, IASTNode container) { + int j= 0; + for (int i = 0; i < set.length; i++) { + IASTName n= set[i]; + if (n == null) + break; + if (container.contains(n)) { + set[i]= null; + } else if (i != j) { + set[j++]= n; + set[i]= null; + } + } + } + protected void doPopulateCache() { final IASTNode scopeNode = physicalNode; IASTNode[] nodes = null; @@ -569,6 +619,7 @@ public class CScope implements ICScope, IASTInternalScope { /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IScope#getScopeName() */ + @Override public IName getScopeName() { if (physicalNode instanceof IASTCompositeTypeSpecifier) { return ((IASTCompositeTypeSpecifier) physicalNode).getName(); @@ -576,15 +627,17 @@ public class CScope implements ICScope, IASTInternalScope { return null; } + @Override public void addBinding(IBinding binding) { int type = NAMESPACE_TYPE_OTHER; if (binding instanceof ICompositeType || binding instanceof IEnumeration) { type = NAMESPACE_TYPE_TAG; } - CharArrayObjectMap map = mapsToNameOrBinding[type]; + @SuppressWarnings("unchecked") + CharArrayObjectMap map = (CharArrayObjectMap) mapsToNameOrBinding[type]; if (map == CharArrayObjectMap.EMPTY_MAP) - map = mapsToNameOrBinding[type] = new CharArrayObjectMap(2); + mapsToNameOrBinding[type] = map= new CharArrayObjectMap(2); map.put(binding.getNameCharArray(), binding); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguityResolver.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguityResolver.java index d31041261e3..3a7043e32cd 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguityResolver.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguityResolver.java @@ -18,7 +18,6 @@ import org.eclipse.cdt.core.dom.ast.ASTVisitor; import org.eclipse.cdt.core.dom.ast.IASTCompositeTypeSpecifier; import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; import org.eclipse.cdt.core.dom.ast.IASTDeclaration; -import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement; import org.eclipse.cdt.core.dom.ast.IASTDeclarator; import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; @@ -85,8 +84,6 @@ final class CPPASTAmbiguityResolver extends ASTVisitor { } node= node.getParent(); } - } else if (node instanceof IASTDeclarationStatement) { - repopulateScope(((IASTDeclarationStatement) node).getDeclaration()); } else if (node instanceof IASTDeclaration) { repopulateScope((IASTDeclaration) node); } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousStatement.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousStatement.java index 3e42da6fbdd..c168e86be94 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousStatement.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPASTAmbiguousStatement.java @@ -11,12 +11,16 @@ *******************************************************************************/ package org.eclipse.cdt.internal.core.dom.parser.cpp; +import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.IASTDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement; import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTStatement; import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.parser.util.ArrayUtil; import org.eclipse.cdt.internal.core.dom.parser.ASTAmbiguousNode; import org.eclipse.cdt.internal.core.dom.parser.IASTAmbiguousStatement; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPSemantics; import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; public class CPPASTAmbiguousStatement extends ASTAmbiguousNode implements @@ -24,6 +28,8 @@ public class CPPASTAmbiguousStatement extends ASTAmbiguousNode implements private IASTStatement [] stmts = new IASTStatement[2]; private int stmtsPos=-1; + private IScope fScope; + private IASTDeclaration fDeclaration; public CPPASTAmbiguousStatement(IASTStatement... statements) { for(IASTStatement s : statements) @@ -32,21 +38,49 @@ public class CPPASTAmbiguousStatement extends ASTAmbiguousNode implements @Override protected void beforeResolution() { - // populate containing scope, so that it will not be affected by the alternative branches. - IScope scope= CPPVisitor.getContainingScope(this); - if (scope instanceof ICPPASTInternalScope) { - ((ICPPASTInternalScope) scope).populateCache(); + // Populate containing scope, so that it will not be affected by the alternative + // branches. + fScope= CPPVisitor.getContainingScope(this); + if (fScope instanceof ICPPASTInternalScope) { + ((ICPPASTInternalScope) fScope).populateCache(); + } + } + + @Override + protected void beforeAlternative(IASTNode alternative) { + cleanupScope(); + if (alternative instanceof IASTDeclarationStatement) { + if (fScope instanceof ICPPASTInternalScope) { + fDeclaration = ((IASTDeclarationStatement) alternative).getDeclaration(); + CPPSemantics.populateCache((ICPPASTInternalScope) fScope, fDeclaration); + } + } + } + + private void cleanupScope() { + if (fScope instanceof ICPPASTInternalScope && fDeclaration != null) { + ((ICPPASTInternalScope) fScope).removeNestedFromCache(fDeclaration); } } - public IASTStatement copy() { + @Override + protected void afterResolution(ASTVisitor resolver, IASTNode best) { + beforeAlternative(best); + fDeclaration= null; + fScope= null; + } + + @Override + public IASTStatement copy() { throw new UnsupportedOperationException(); } + @Override public IASTStatement copy(CopyStyle style) { throw new UnsupportedOperationException(); } + @Override public void addStatement(IASTStatement s) { assertNotFrozen(); if (s != null) { @@ -56,7 +90,8 @@ public class CPPASTAmbiguousStatement extends ASTAmbiguousNode implements } } - public IASTStatement[] getStatements() { + @Override + public IASTStatement[] getStatements() { stmts = (IASTStatement[]) ArrayUtil.removeNullsAfter( IASTStatement.class, stmts, stmtsPos ); return stmts; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecializationScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecializationScope.java index bdb119baa53..b03b19a2dd8 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecializationScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPClassSpecializationScope.java @@ -28,8 +28,14 @@ public class CPPClassSpecializationScope extends AbstractCPPClassSpecializationS } // This scope does not cache its own names + @Override public void addName(IASTName name) {} + @Override public IASTNode getPhysicalNode() { return null; } + @Override public void addBinding(IBinding binding) {} + @Override public void populateCache() {} + @Override + public void removeNestedFromCache(IASTNode container) {} } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScope.java index e928a663cfb..15707e5fcdb 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPScope.java @@ -60,7 +60,7 @@ abstract public class CPPScope implements ICPPASTInternalScope { private IASTNode physicalNode; private boolean isCached = false; - protected CharArrayObjectMap bindings = null; + protected CharArrayObjectMap bindings = null; private ICPPNamespace fIndexNamespace= UNINITIALIZED; public static class CPPScopeProblem extends ProblemBinding implements ICPPScope { @@ -76,14 +76,17 @@ abstract public class CPPScope implements ICPPASTInternalScope { this.physicalNode = physicalNode; } + @Override public IScope getParent() throws DOMException { return CPPVisitor.getContainingNonTemplateScope(physicalNode); } + @Override public IASTNode getPhysicalNode() { return physicalNode; } + @Override @SuppressWarnings({ "unchecked" }) public void addName(IASTName name) { // don't add inactive names to the scope @@ -91,7 +94,7 @@ abstract public class CPPScope implements ICPPASTInternalScope { return; if (bindings == null) - bindings = new CharArrayObjectMap(1); + bindings = new CharArrayObjectMap(1); if (name instanceof ICPPASTQualifiedName) { if (!(physicalNode instanceof ICPPASTCompositeTypeSpecifier) && !(physicalNode instanceof ICPPASTNamespaceDefinition)) { @@ -144,6 +147,7 @@ abstract public class CPPScope implements ICPPASTInternalScope { } } + @Override public IBinding getBinding(IASTName name, boolean forceResolve, IIndexFileSet fileSet) { IBinding binding= getBindingInAST(name, forceResolve); if (binding == null && forceResolve) { @@ -198,10 +202,12 @@ abstract public class CPPScope implements ICPPASTInternalScope { return CPPSemantics.resolveAmbiguities(name, bs); } + @Override public final IBinding[] getBindings(IASTName name, boolean resolve, boolean prefixLookup, IIndexFileSet fileSet) { return getBindings(name, resolve, prefixLookup, fileSet, true); } + @Override public IBinding[] getBindings(IASTName name, boolean resolve, boolean prefixLookup, IIndexFileSet fileSet, boolean checkPointOfDecl) { IBinding[] result = getBindingsInAST(name, resolve, prefixLookup, checkPointOfDecl); @@ -316,24 +322,63 @@ abstract public class CPPScope implements ICPPASTInternalScope { return (IBinding[]) ArrayUtil.append(IBinding.class, result, binding); } + @Override public final void populateCache() { if (!isCached) { CPPSemantics.populateCache(this); isCached= true; } } + + @Override + public void removeNestedFromCache(IASTNode container) { + if (bindings != null) { + removeFromMap(bindings, container); + } + } + + private void removeFromMap(CharArrayObjectMap map, IASTNode container) { + for (int i = 0; i < map.size(); i++) { + Object o= map.getAt(i); + if (o instanceof IASTName) { + if (container.contains((IASTNode) o)) { + final char[] key = map.keyAt(i); + map.remove(key, 0, key.length); + i--; + } + } else if (o instanceof ObjectSet) { + @SuppressWarnings("unchecked") + final ObjectSet set = (ObjectSet) o; + removeFromSet(set, container); + } + } + } + + private void removeFromSet(ObjectSet set, IASTNode container) { + for (int i = 0; i < set.size(); i++) { + Object o= set.keyAt(i); + if (o instanceof IASTName) { + if (container.contains((IASTNode) o)) { + set.remove(o); + i--; + } + } + } + } /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IScope#find(java.lang.String) */ + @Override public IBinding[] find(String name) { return CPPSemantics.findBindings(this, name, false); } + @Override @SuppressWarnings({ "unchecked" }) public void addBinding(IBinding binding) { if (bindings == null) - bindings = new CharArrayObjectMap(1); + bindings = new CharArrayObjectMap(1); char[] c = binding.getNameCharArray(); if (c.length == 0) { return; @@ -353,14 +398,17 @@ abstract public class CPPScope implements ICPPASTInternalScope { } } + @Override public final IBinding getBinding(IASTName name, boolean resolve) { return getBinding(name, resolve, IIndexFileSet.EMPTY); } + @Override public final IBinding[] getBindings(IASTName name, boolean resolve, boolean prefix) { return getBindings(name, resolve, prefix, IIndexFileSet.EMPTY, true); } + @Override public IName getScopeName() { return null; } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownScope.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownScope.java index 20ca20dedd2..b1377c38173 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownScope.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPUnknownScope.java @@ -52,6 +52,7 @@ public class CPPUnknownScope implements ICPPInternalUnknownScope { this.binding = binding; } + @Override public EScopeKind getKind() { return EScopeKind.eClassType; } @@ -59,37 +60,43 @@ public class CPPUnknownScope implements ICPPInternalUnknownScope { /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IScope#getScopeName() */ - public IName getScopeName() { + @Override + public IName getScopeName() { return scopeName; } /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IScope#getParent() */ - public IScope getParent() throws DOMException { + @Override + public IScope getParent() throws DOMException { return binding.getScope(); } /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IScope#find(java.lang.String) */ - public IBinding[] find(String name) { + @Override + public IBinding[] find(String name) { return null; } /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IScope#getPhysicalNode() */ - public IASTNode getPhysicalNode() { + @Override + public IASTNode getPhysicalNode() { return scopeName; } /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IScope#addName(org.eclipse.cdt.core.dom.ast.IASTName) */ - public void addName(IASTName name) { + @Override + public void addName(IASTName name) { } + @Override public final IBinding getBinding(IASTName name, boolean resolve) { return getBinding(name, resolve, IIndexFileSet.EMPTY); } @@ -97,7 +104,8 @@ public class CPPUnknownScope implements ICPPInternalUnknownScope { /* (non-Javadoc) * @see org.eclipse.cdt.core.dom.ast.IScope#getBinding(org.eclipse.cdt.core.dom.ast.IASTName, boolean) */ - public IBinding getBinding(final IASTName name, boolean resolve, IIndexFileSet fileSet) { + @Override + public IBinding getBinding(final IASTName name, boolean resolve, IIndexFileSet fileSet) { boolean type= false; boolean function= false; @@ -171,15 +179,18 @@ public class CPPUnknownScope implements ICPPInternalUnknownScope { return result; } + @Override public final IBinding[] getBindings(IASTName name, boolean resolve, boolean prefix) { return getBindings(name, resolve, prefix, IIndexFileSet.EMPTY); } - public final IBinding[] getBindings(IASTName name, boolean resolve, boolean prefixLookup, IIndexFileSet fileSet) { + @Override + public final IBinding[] getBindings(IASTName name, boolean resolve, boolean prefixLookup, IIndexFileSet fileSet) { return getBindings(name, resolve, prefixLookup, fileSet, true); } - public IBinding[] getBindings(IASTName name, boolean resolve, boolean prefixLookup, IIndexFileSet acceptLocalBindings, boolean checkPointOfDecl) { + @Override + public IBinding[] getBindings(IASTName name, boolean resolve, boolean prefixLookup, IIndexFileSet acceptLocalBindings, boolean checkPointOfDecl) { if (prefixLookup) { if (binding instanceof ICPPDeferredClassInstance) { ICPPDeferredClassInstance instance = (ICPPDeferredClassInstance) binding; @@ -194,6 +205,7 @@ public class CPPUnknownScope implements ICPPInternalUnknownScope { return new IBinding[] {getBinding(name, resolve, acceptLocalBindings)}; } + @Override public void addBinding(IBinding binding) { // do nothing, this is part of template magic and not a normal scope } @@ -201,6 +213,7 @@ public class CPPUnknownScope implements ICPPInternalUnknownScope { /* (non-Javadoc) * @see org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalUnknownScope#getUnknownBinding() */ + @Override public ICPPBinding getScopeBinding() { return binding; } @@ -213,5 +226,9 @@ public class CPPUnknownScope implements ICPPInternalUnknownScope { return scopeName.toString(); } + @Override public void populateCache() {} + + @Override + public void removeNestedFromCache(IASTNode container) {} } diff --git a/lrparser/org.eclipse.cdt.core.lrparser/old/org/eclipse/cdt/internal/core/dom/lrparser/c99/bindings/C99Scope.java b/lrparser/org.eclipse.cdt.core.lrparser/old/org/eclipse/cdt/internal/core/dom/lrparser/c99/bindings/C99Scope.java index 58251314dd2..9e7b7933f7f 100644 --- a/lrparser/org.eclipse.cdt.core.lrparser/old/org/eclipse/cdt/internal/core/dom/lrparser/c99/bindings/C99Scope.java +++ b/lrparser/org.eclipse.cdt.core.lrparser/old/org/eclipse/cdt/internal/core/dom/lrparser/c99/bindings/C99Scope.java @@ -92,6 +92,9 @@ public class C99Scope implements IC99Scope, IASTInternalScope { public void populateCache() { } + public void removeNestedFromCache(IASTNode container) { + } + public IBinding getBinding(IASTName name, boolean resolve, IIndexFileSet acceptLocalBindings) { // TODO Auto-generated method stub