mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-09 18:56:02 +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.ILinkage;
|
||||||
import org.eclipse.cdt.core.dom.IName;
|
import org.eclipse.cdt.core.dom.IName;
|
||||||
import org.eclipse.cdt.core.dom.IPDOMManager;
|
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.IASTName;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBasicType;
|
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.IIndexName;
|
||||||
import org.eclipse.cdt.core.index.IndexFilter;
|
import org.eclipse.cdt.core.index.IndexFilter;
|
||||||
import org.eclipse.cdt.core.index.IndexLocationFactory;
|
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.ICProject;
|
||||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||||
import org.eclipse.cdt.core.testplugin.CProjectHelper;
|
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.CCorePlugin;
|
||||||
import org.eclipse.cdt.core.dom.ast.DOMException;
|
import org.eclipse.cdt.core.dom.ast.DOMException;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
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.IType;
|
||||||
import org.eclipse.cdt.core.dom.ast.ITypedef;
|
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.Util;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
|
import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
|
||||||
import org.eclipse.cdt.internal.core.index.IIndexCBindingConstants;
|
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 {
|
private void setType(final PDOMLinkage linkage, IType newType) throws CoreException, DOMException {
|
||||||
PDOMNode typeNode = linkage.addType(this, newType);
|
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() {
|
protected int getRecordSize() {
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
* http://www.eclipse.org/legal/epl-v10.html
|
* http://www.eclipse.org/legal/epl-v10.html
|
||||||
*
|
*
|
||||||
* Contributors:
|
* Contributors:
|
||||||
* QNX - Initial API and implementation
|
* QNX - Initial API and implementation
|
||||||
* Markus Schorn (Wind River Systems)
|
* Markus Schorn (Wind River Systems)
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
package org.eclipse.cdt.internal.core.pdom.dom.cpp;
|
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.DOMException;
|
||||||
import org.eclipse.cdt.core.dom.ast.IASTName;
|
import org.eclipse.cdt.core.dom.ast.IASTName;
|
||||||
import org.eclipse.cdt.core.dom.ast.IBinding;
|
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.IType;
|
||||||
import org.eclipse.cdt.core.dom.ast.ITypedef;
|
import org.eclipse.cdt.core.dom.ast.ITypedef;
|
||||||
import org.eclipse.cdt.core.dom.ast.cpp.ICPPDelegate;
|
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.Util;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.ITypeContainer;
|
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.CPPTypedef;
|
||||||
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPDelegateCreator;
|
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.CPPTypedefClone;
|
||||||
|
import org.eclipse.cdt.internal.core.index.IIndexCPPBindingConstants;
|
||||||
import org.eclipse.cdt.internal.core.index.IIndexType;
|
import org.eclipse.cdt.internal.core.index.IIndexType;
|
||||||
import org.eclipse.cdt.internal.core.pdom.PDOM;
|
import org.eclipse.cdt.internal.core.pdom.PDOM;
|
||||||
import org.eclipse.cdt.internal.core.pdom.dom.PDOMBinding;
|
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 {
|
private void setType(final PDOMLinkage linkage, IType newType) throws CoreException, DOMException {
|
||||||
PDOMNode typeNode = linkage.addType(this, newType);
|
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);
|
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() {
|
protected int getRecordSize() {
|
||||||
return RECORD_SIZE;
|
return RECORD_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getNodeType() {
|
public int getNodeType() {
|
||||||
return PDOMCPPLinkage.CPPTYPEDEF;
|
return IIndexCPPBindingConstants.CPPTYPEDEF;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IType getType() {
|
public IType getType() {
|
||||||
|
|
Loading…
Add table
Reference in a new issue