mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Fix and testcase for 200553, infinite loop with recursive typedefs.
This commit is contained in:
parent
cf73aadd70
commit
5515df94b7
3 changed files with 175 additions and 5 deletions
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Add table
Reference in a new issue