diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java index 27eb4e0f8ff..948c371ecaf 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/internal/index/tests/IndexBugsTests.java @@ -24,6 +24,7 @@ import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ILinkage; import org.eclipse.cdt.core.dom.IName; import org.eclipse.cdt.core.dom.IPDOMManager; +import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.dom.ast.IBasicType; @@ -46,6 +47,7 @@ import org.eclipse.cdt.core.index.IIndexManager; import org.eclipse.cdt.core.index.IIndexName; import org.eclipse.cdt.core.index.IndexFilter; import org.eclipse.cdt.core.index.IndexLocationFactory; +import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.model.ITranslationUnit; import org.eclipse.cdt.core.testplugin.CProjectHelper; @@ -946,4 +948,98 @@ public class IndexBugsTests extends BaseTestCase { } } + + // typedef bug200553_A bug200553_B; + // typedef bug200553_B bug200553_A; + public void testTypedefRecursionCpp_Bug200553() throws Exception { + StringBuffer[] contents= getContentsForTest(1); + final IIndexManager indexManager = CCorePlugin.getIndexManager(); + IFile f1= TestSourceReader.createFile(fCProject.getProject(), "src.cpp", contents[0].toString()); + waitForIndexer(); + fIndex.acquireReadLock(); + try { + IIndexBinding[] bindings= fIndex.findBindings("bug200553_A".toCharArray(), IndexFilter.ALL, NPM); + assertEquals(1, bindings.length); + assertTrue(bindings[0] instanceof ITypedef); + checkTypedefDepth((ITypedef) bindings[0]); + + bindings= fIndex.findBindings("bug200553_B".toCharArray(), IndexFilter.ALL, NPM); + assertEquals(1, bindings.length); + assertTrue(bindings[0] instanceof ITypedef); + checkTypedefDepth((ITypedef) bindings[0]); + } + finally { + fIndex.releaseReadLock(); + } + + indexManager.update(new ICElement[] {fCProject}, IIndexManager.UPDATE_ALL); + waitForIndexer(); + fIndex.acquireReadLock(); + try { + IIndexBinding[] bindings= fIndex.findBindings("bug200553_A".toCharArray(), IndexFilter.ALL, NPM); + assertEquals(1, bindings.length); + assertTrue(bindings[0] instanceof ITypedef); + checkTypedefDepth((ITypedef) bindings[0]); + + bindings= fIndex.findBindings("bug200553_B".toCharArray(), IndexFilter.ALL, NPM); + assertEquals(1, bindings.length); + assertTrue(bindings[0] instanceof ITypedef); + checkTypedefDepth((ITypedef) bindings[0]); + } + finally { + fIndex.releaseReadLock(); + } + } + + private void checkTypedefDepth(ITypedef td) throws DOMException { + int maxDepth= 20; + IType type= td; + while (--maxDepth > 0 && type instanceof ITypedef) { + type= ((ITypedef) type).getType(); + } + assertTrue(maxDepth > 0); + } + + // typedef bug200553_A bug200553_B; + // typedef bug200553_B bug200553_A; + public void testTypedefRecursionC_Bug200553() throws Exception { + StringBuffer[] contents= getContentsForTest(1); + final IIndexManager indexManager = CCorePlugin.getIndexManager(); + IFile f1= TestSourceReader.createFile(fCProject.getProject(), "src.c", contents[0].toString()); + waitForIndexer(); + fIndex.acquireReadLock(); + try { + IIndexBinding[] bindings= fIndex.findBindings("bug200553_A".toCharArray(), IndexFilter.ALL, NPM); + assertEquals(1, bindings.length); + assertTrue(bindings[0] instanceof ITypedef); + checkTypedefDepth((ITypedef) bindings[0]); + + bindings= fIndex.findBindings("bug200553_B".toCharArray(), IndexFilter.ALL, NPM); + assertEquals(1, bindings.length); + assertTrue(bindings[0] instanceof ITypedef); + checkTypedefDepth((ITypedef) bindings[0]); + } + finally { + fIndex.releaseReadLock(); + } + + indexManager.update(new ICElement[] {fCProject}, IIndexManager.UPDATE_ALL); + waitForIndexer(); + fIndex.acquireReadLock(); + try { + IIndexBinding[] bindings= fIndex.findBindings("bug200553_A".toCharArray(), IndexFilter.ALL, NPM); + assertEquals(1, bindings.length); + assertTrue(bindings[0] instanceof ITypedef); + checkTypedefDepth((ITypedef) bindings[0]); + + bindings= fIndex.findBindings("bug200553_B".toCharArray(), IndexFilter.ALL, NPM); + assertEquals(1, bindings.length); + assertTrue(bindings[0] instanceof ITypedef); + checkTypedefDepth((ITypedef) bindings[0]); + } + finally { + fIndex.releaseReadLock(); + } + } + } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCTypedef.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCTypedef.java index c0fc61ae150..231a5739cb4 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCTypedef.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/c/PDOMCTypedef.java @@ -15,8 +15,10 @@ package org.eclipse.cdt.internal.core.pdom.dom.c; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IFunctionType; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.ITypedef; +import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.Util; import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer; import org.eclipse.cdt.internal.core.index.IIndexCBindingConstants; @@ -67,10 +69,44 @@ class PDOMCTypedef extends PDOMBinding implements ITypedef, ITypeContainer, IInd } } } - + private void setType(final PDOMLinkage linkage, IType newType) throws CoreException, DOMException { PDOMNode typeNode = linkage.addType(this, newType); - pdom.getDB().putInt(record+TYPE, typeNode != null ? typeNode.getRecord() : 0); + if (introducesRecursion((IType) typeNode, getNameCharArray())) { + linkage.deleteType((IType) typeNode, record); + typeNode= null; + } + pdom.getDB().putInt(record + TYPE, typeNode != null ? typeNode.getRecord() : 0); + } + + private boolean introducesRecursion(IType type, char[] tdname) throws DOMException { + int maxDepth= 50; + while (--maxDepth > 0) { + if (type instanceof ITypedef && CharArrayUtils.equals(((ITypedef) type).getNameCharArray(), tdname)) { + return true; + } + if (type instanceof ITypeContainer) { + type= ((ITypeContainer) type).getType(); + } + else if (type instanceof IFunctionType) { + IFunctionType ft= (IFunctionType) type; + if (introducesRecursion(ft.getReturnType(), tdname)) { + return true; + } + IType[] params= ft.getParameterTypes(); + for (int i = 0; i < params.length; i++) { + IType param = params[i]; + if (introducesRecursion(param, tdname)) { + return true; + } + } + return false; + } + else { + return false; + } + } + return true; } protected int getRecordSize() { diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPTypedef.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPTypedef.java index 04e5563fb3c..dd9db020887 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPTypedef.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/pdom/dom/cpp/PDOMCPPTypedef.java @@ -6,8 +6,8 @@ * http://www.eclipse.org/legal/epl-v10.html * * Contributors: - * QNX - Initial API and implementation - * Markus Schorn (Wind River Systems) + * QNX - Initial API and implementation + * Markus Schorn (Wind River Systems) *******************************************************************************/ package org.eclipse.cdt.internal.core.pdom.dom.cpp; @@ -15,14 +15,17 @@ import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ast.DOMException; import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IFunctionType; import org.eclipse.cdt.core.dom.ast.IType; import org.eclipse.cdt.core.dom.ast.ITypedef; import org.eclipse.cdt.core.dom.ast.cpp.ICPPDelegate; +import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.internal.core.Util; import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer; import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPTypedef; import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDelegateCreator; import org.eclipse.cdt.internal.core.index.CPPTypedefClone; +import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants; import org.eclipse.cdt.internal.core.index.IIndexType; import org.eclipse.cdt.internal.core.pdom.PDOM; import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding; @@ -72,15 +75,50 @@ class PDOMCPPTypedef extends PDOMCPPBinding private void setType(final PDOMLinkage linkage, IType newType) throws CoreException, DOMException { PDOMNode typeNode = linkage.addType(this, newType); + if (introducesRecursion((IType) typeNode, getNameCharArray())) { + linkage.deleteType((IType) typeNode, record); + typeNode= null; + } pdom.getDB().putInt(record + TYPE, typeNode != null ? typeNode.getRecord() : 0); } + private boolean introducesRecursion(IType type, char[] tdname) throws DOMException { + int maxDepth= 50; + while (--maxDepth > 0) { + if (type instanceof ITypedef && CharArrayUtils.equals(((ITypedef) type).getNameCharArray(), tdname)) { + return true; + } + if (type instanceof ITypeContainer) { + type= ((ITypeContainer) type).getType(); + } + else if (type instanceof IFunctionType) { + IFunctionType ft= (IFunctionType) type; + if (introducesRecursion(ft.getReturnType(), tdname)) { + return true; + } + IType[] params= ft.getParameterTypes(); + for (int i = 0; i < params.length; i++) { + IType param = params[i]; + if (introducesRecursion(param, tdname)) { + return true; + } + } + return false; + } + else { + return false; + } + } + return true; + } + + protected int getRecordSize() { return RECORD_SIZE; } public int getNodeType() { - return PDOMCPPLinkage.CPPTYPEDEF; + return IIndexCPPBindingConstants.CPPTYPEDEF; } public IType getType() {