1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-21 16:05:25 +02:00

191251: fix names improperly resolving to bindings relating to self-referencing typedefs

This commit is contained in:
Andrew Ferguson 2007-06-14 12:46:06 +00:00
parent 6760d0c61d
commit 75e338c2f8
6 changed files with 143 additions and 15 deletions

View file

@ -394,7 +394,7 @@ public class AST2BaseTest extends BaseTestCase {
} }
protected static void assertInstance(Object o, Class c) { protected static void assertInstance(Object o, Class c) {
assertNotNull(o); assertNotNull("Expected object of "+c.getName()+" but got a null value", o);
assertTrue("Expected "+c.getName()+" but got "+o.getClass().getName(), c.isInstance(o)); assertTrue("Expected "+c.getName()+" but got "+o.getClass().getName(), c.isInstance(o));
} }
} }

View file

@ -1505,7 +1505,7 @@ public class AST2CSpecTest extends AST2SpecBaseTest {
public void test6_7_8s34() throws Exception { public void test6_7_8s34() throws Exception {
StringBuffer buffer = new StringBuffer(); StringBuffer buffer = new StringBuffer();
buffer.append("div_t answer = { .quot = 2, .rem = -1 };\n"); //$NON-NLS-1$ buffer.append("div_t answer = { .quot = 2, .rem = -1 };\n"); //$NON-NLS-1$
parse(buffer.toString(), ParserLanguage.C, true, 0); parse(buffer.toString(), ParserLanguage.C, true, 1); // div_t (correctly) cannot be resolved
} }
/** /**

View file

@ -113,9 +113,9 @@ public class AST2Tests extends AST2BaseTest {
super(name); super(name);
} }
public void testBug75189() throws Exception { public void testBug75189() throws Exception {
parseAndCheckBindings( "struct A{};typedef int (*F) (A*);" ); //$NON-NLS-1$ parseAndCheckBindings( "struct A{};\n typedef int (*F) (struct A*);" ); //$NON-NLS-1$
parseAndCheckBindings( "struct A{};\n typedef int (*F) (A*);", ParserLanguage.CPP ); //$NON-NLS-1$
} }
public void testBug75340() throws Exception { public void testBug75340() throws Exception {
@ -1873,7 +1873,7 @@ public class AST2Tests extends AST2BaseTest {
assertEquals(decls.length, 1); assertEquals(decls.length, 1);
assertEquals(decls[0], name_A1); assertEquals(decls[0], name_A1);
assertNull(name_d.resolveBinding()); assertNull("Expected null, got "+name_d.resolveBinding(), name_d.resolveBinding());
} }
public void testDesignatedInitializers() throws ParserException { public void testDesignatedInitializers() throws ParserException {
@ -3835,4 +3835,36 @@ public class AST2Tests extends AST2BaseTest {
buffer.append("string\";\n" ); //$NON-NLS-1$ buffer.append("string\";\n" ); //$NON-NLS-1$
parseAndCheckBindings( buffer.toString() ); parseAndCheckBindings( buffer.toString() );
} }
// typedef A B;
// typedef C D;
// typedef E E;
// typedef typeof(G) G;
// typedef H *H;
// typedef I *************I;
// typedef int (*J)(J);
public void testBug192165() throws Exception {
String content= getContents(1)[0].toString();
for (int i = 0; i < LANGUAGES.length; i++) {
IASTTranslationUnit tu = parse( content, LANGUAGES[i], true, false );
CNameCollector col = new CNameCollector();
tu.accept(col);
assertInstance(col.getName(0).resolveBinding(), IProblemBinding.class);
assertInstance(col.getName(1).resolveBinding(), ITypedef.class);
assertInstance(col.getName(2).resolveBinding(), IProblemBinding.class);
assertInstance(col.getName(3).resolveBinding(), ITypedef.class);
assertInstance(col.getName(4).resolveBinding(), IProblemBinding.class);
assertInstance(col.getName(5).resolveBinding(), ITypedef.class);
assertInstance(col.getName(6).resolveBinding(), IProblemBinding.class);
assertInstance(col.getName(7).resolveBinding(), ITypedef.class);
assertInstance(col.getName(8).resolveBinding(), IProblemBinding.class);
assertInstance(col.getName(9).resolveBinding(), ITypedef.class);
assertInstance(col.getName(10).resolveBinding(), IProblemBinding.class);
assertInstance(col.getName(11).resolveBinding(), ITypedef.class);
// function ptr
assertInstance(col.getName(12).resolveBinding(), ITypedef.class);
assertInstance(col.getName(13).resolveBinding(), IProblemBinding.class);
}
}
} }

View file

@ -10,15 +10,28 @@
*******************************************************************************/ *******************************************************************************/
package org.eclipse.cdt.internal.pdom.tests; package org.eclipse.cdt.internal.pdom.tests;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
import junit.framework.Test; import junit.framework.Test;
import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.IPDOMManager; import org.eclipse.cdt.core.dom.IPDOMManager;
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.index.IndexFilter;
import org.eclipse.cdt.core.model.ICProject; import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.testplugin.CProjectHelper; import org.eclipse.cdt.core.testplugin.CProjectHelper;
import org.eclipse.cdt.core.testplugin.CTestPlugin; import org.eclipse.cdt.core.testplugin.CTestPlugin;
import org.eclipse.cdt.core.testplugin.util.BaseTestCase; import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
import org.eclipse.cdt.core.testplugin.util.TestSourceReader; import org.eclipse.cdt.core.testplugin.util.TestSourceReader;
import org.eclipse.cdt.internal.core.CCoreInternals;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPSemantics;
import org.eclipse.cdt.internal.core.pdom.PDOM;
import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor;
@ -27,6 +40,7 @@ import org.osgi.framework.Bundle;
public class PDOMCBugsTest extends BaseTestCase { public class PDOMCBugsTest extends BaseTestCase {
ICProject cproject; ICProject cproject;
PDOM pdom;
public static Test suite() { public static Test suite() {
return suite(PDOMCBugsTest.class); return suite(PDOMCBugsTest.class);
@ -41,6 +55,7 @@ public class PDOMCBugsTest extends BaseTestCase {
CCorePlugin.getIndexManager().setIndexerId(cproject, IPDOMManager.ID_FAST_INDEXER); CCorePlugin.getIndexManager().setIndexerId(cproject, IPDOMManager.ID_FAST_INDEXER);
assertTrue(CCorePlugin.getIndexManager().joinIndexer(360000, new NullProgressMonitor())); assertTrue(CCorePlugin.getIndexManager().joinIndexer(360000, new NullProgressMonitor()));
pdom= (PDOM) CCoreInternals.getPDOMManager().getPDOM(cproject);
super.setUp(); super.setUp();
} }
@ -51,10 +66,37 @@ public class PDOMCBugsTest extends BaseTestCase {
super.tearDown(); super.tearDown();
} }
// typedef typeof(T) T; // // check we get the right IProblemBinding objects
public void _test192165() { // typedef A B;
// a StackOverflow occurs at this point // typedef C D;
// typedef E E;
// typedef typeof(G) G;
// typedef H *H;
// typedef I *************I;
// typedef int (*J)(J);
public void test192165() throws Exception {
pdom.acquireReadLock();
IBinding[] bindings= pdom.findBindings(Pattern.compile(".*"), false, IndexFilter.ALL, NPM);
assertEquals(7, bindings.length);
Set bnames= new HashSet();
for(int i=0; i<bindings.length; i++) {
assertTrue("expected typedef, got "+bindings[i], bindings[i] instanceof ITypedef);
bnames.add(bindings[i].getName());
IType type= CPPSemantics.getUltimateType((IType)bindings[i], false);
if(bindings[i].getName().equals("J")) {
assertTrue(type instanceof IFunctionType);
IFunctionType ft= (IFunctionType) type;
assertEquals(1, ft.getParameterTypes().length);
assertNull(ft.getParameterTypes()[0]);
} else {
assertNull("expected null, got "+type, type);
}
} }
public void testDummy() {} Set expected= new HashSet(Arrays.asList(new String[]{"B","D","E","G","H","I","J"}));
assertEquals(expected, bnames);
pdom.releaseReadLock();
}
} }

View file

@ -40,6 +40,7 @@ import org.eclipse.cdt.core.dom.ast.IEnumeration;
import org.eclipse.cdt.core.dom.ast.IFunction; import org.eclipse.cdt.core.dom.ast.IFunction;
import org.eclipse.cdt.core.dom.ast.IScope; import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.c.CASTVisitor; import org.eclipse.cdt.core.dom.ast.c.CASTVisitor;
import org.eclipse.cdt.core.dom.ast.c.ICASTTypedefNameSpecifier;
import org.eclipse.cdt.core.dom.ast.c.ICScope; import org.eclipse.cdt.core.dom.ast.c.ICScope;
import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.index.IIndex;
import org.eclipse.cdt.core.index.IndexFilter; import org.eclipse.cdt.core.index.IndexFilter;
@ -201,12 +202,20 @@ public class CScope implements ICScope, IASTInternalScope {
if( o instanceof IBinding ) if( o instanceof IBinding )
return (IBinding) o; return (IBinding) o;
if( (resolve || ((IASTName)o).getBinding() != null) && ( o != name ) ) IASTName foundName= (IASTName) o;
return ((IASTName)o).resolveBinding(); if( (resolve || foundName.getBinding() != null) && ( foundName != name ) ) {
if(!isTypeDefinition(name) || CVisitor.declaredBefore(foundName, name)) {
return foundName.resolveBinding();
}
}
return null; return null;
} }
private boolean isTypeDefinition(IASTName name) {
return name.getPropertyInParent()==ICASTTypedefNameSpecifier.NAME;
}
/* (non-Javadoc) /* (non-Javadoc)
* @see org.eclipse.cdt.core.dom.ast.c.ICScope#getBinding(org.eclipse.cdt.core.dom.ast.IASTName, boolean) * @see org.eclipse.cdt.core.dom.ast.c.ICScope#getBinding(org.eclipse.cdt.core.dom.ast.IASTName, boolean)
*/ */

View file

@ -45,6 +45,7 @@ import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTGotoStatement; import org.eclipse.cdt.core.dom.ast.IASTGotoStatement;
import org.eclipse.cdt.core.dom.ast.IASTIdExpression; import org.eclipse.cdt.core.dom.ast.IASTIdExpression;
import org.eclipse.cdt.core.dom.ast.IASTInitializer;
import org.eclipse.cdt.core.dom.ast.IASTLabelStatement; import org.eclipse.cdt.core.dom.ast.IASTLabelStatement;
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression; import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
import org.eclipse.cdt.core.dom.ast.IASTName; import org.eclipse.cdt.core.dom.ast.IASTName;
@ -103,6 +104,7 @@ import org.eclipse.cdt.core.parser.util.CharArrayObjectMap;
import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.core.parser.util.CharArrayUtils;
import org.eclipse.cdt.core.parser.util.ObjectSet; import org.eclipse.cdt.core.parser.util.ObjectSet;
import org.eclipse.cdt.internal.core.dom.parser.ASTInternal; import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
import org.eclipse.cdt.internal.core.dom.parser.ASTNode;
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.ProblemBinding; import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.CoreException;
@ -993,7 +995,10 @@ public class CVisitor {
} else if( node instanceof ICASTTypedefNameSpecifier ){ } else if( node instanceof ICASTTypedefNameSpecifier ){
IASTNode blockItem = getContainingBlockItem( node ); IASTNode blockItem = getContainingBlockItem( node );
try { try {
IBinding binding = (IBinding) findBinding( blockItem, ((ICASTTypedefNameSpecifier)node).getName(), bits ); IASTName name= ((ICASTTypedefNameSpecifier)node).getName();
IBinding binding = (IBinding) findBinding( blockItem, name, bits );
if( binding == null )
return new ProblemBinding( node, IProblemBinding.SEMANTIC_NAME_NOT_FOUND, name.toCharArray());
if( binding instanceof IType ) if( binding instanceof IType )
return binding; return binding;
else if( binding != null ) else if( binding != null )
@ -1318,9 +1323,11 @@ public class CVisitor {
} }
} }
if( result != null ){ if( result != null ){
if(CVisitor.declaredBefore((IASTName)result, name)) {
return ((IASTName)result).resolveBinding(); return ((IASTName)result).resolveBinding();
} }
} }
}
if( (bits & CURRENT_SCOPE) == 0 ) if( (bits & CURRENT_SCOPE) == 0 )
blockItem = parent; blockItem = parent;
else else
@ -2031,4 +2038,42 @@ public class CVisitor {
return result; return result;
} }
static public boolean declaredBefore(IASTNode nodeA, IASTNode nodeB){
if( nodeB == null ) return true;
if( nodeB.getPropertyInParent() == STRING_LOOKUP_PROPERTY ) return true;
if(nodeA instanceof ASTNode) {
ASTNode nd= (ASTNode) nodeA;
int pointOfDecl = 0;
ASTNodeProperty prop = nd.getPropertyInParent();
//point of declaration for a name is immediately after its complete declarator and before its initializer
if( prop == IASTDeclarator.DECLARATOR_NAME || nd instanceof IASTDeclarator ){
IASTDeclarator dtor = (IASTDeclarator)((nd instanceof IASTDeclarator) ? nd : nd.getParent());
while( dtor.getParent() instanceof IASTDeclarator )
dtor = (IASTDeclarator) dtor.getParent();
IASTInitializer init = dtor.getInitializer();
if( init != null )
pointOfDecl = ((ASTNode)init).getOffset() - 1;
else
pointOfDecl = ((ASTNode)dtor).getOffset() + ((ASTNode)dtor).getLength();
}
//point of declaration for an enumerator is immediately after it enumerator-definition
else if( prop == IASTEnumerator.ENUMERATOR_NAME) {
IASTEnumerator enumtor = (IASTEnumerator) nd.getParent();
if( enumtor.getValue() != null ){
ASTNode exp = (ASTNode) enumtor.getValue();
pointOfDecl = exp.getOffset() + exp.getLength();
} else {
pointOfDecl = nd.getOffset() + nd.getLength();
}
} else
pointOfDecl = nd.getOffset() + nd.getLength();
return ( pointOfDecl < ((ASTNode)nodeB).getOffset() );
}
return true;
}
} }