1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-16 21:45:22 +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) {
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));
}
}

View file

@ -1505,7 +1505,7 @@ public class AST2CSpecTest extends AST2SpecBaseTest {
public void test6_7_8s34() throws Exception {
StringBuffer buffer = new StringBuffer();
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);
}
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 {
@ -1873,7 +1873,7 @@ public class AST2Tests extends AST2BaseTest {
assertEquals(decls.length, 1);
assertEquals(decls[0], name_A1);
assertNull(name_d.resolveBinding());
assertNull("Expected null, got "+name_d.resolveBinding(), name_d.resolveBinding());
}
public void testDesignatedInitializers() throws ParserException {
@ -3835,4 +3835,36 @@ public class AST2Tests extends AST2BaseTest {
buffer.append("string\";\n" ); //$NON-NLS-1$
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;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
import junit.framework.Test;
import org.eclipse.cdt.core.CCorePlugin;
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.testplugin.CProjectHelper;
import org.eclipse.cdt.core.testplugin.CTestPlugin;
import org.eclipse.cdt.core.testplugin.util.BaseTestCase;
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.IResource;
import org.eclipse.core.runtime.NullProgressMonitor;
@ -27,6 +40,7 @@ import org.osgi.framework.Bundle;
public class PDOMCBugsTest extends BaseTestCase {
ICProject cproject;
PDOM pdom;
public static Test suite() {
return suite(PDOMCBugsTest.class);
@ -41,6 +55,7 @@ public class PDOMCBugsTest extends BaseTestCase {
CCorePlugin.getIndexManager().setIndexerId(cproject, IPDOMManager.ID_FAST_INDEXER);
assertTrue(CCorePlugin.getIndexManager().joinIndexer(360000, new NullProgressMonitor()));
pdom= (PDOM) CCoreInternals.getPDOMManager().getPDOM(cproject);
super.setUp();
}
@ -51,10 +66,37 @@ public class PDOMCBugsTest extends BaseTestCase {
super.tearDown();
}
// typedef typeof(T) T;
public void _test192165() {
// a StackOverflow occurs at this point
// // check we get the right IProblemBinding objects
// 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 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);
}
}
Set expected= new HashSet(Arrays.asList(new String[]{"B","D","E","G","H","I","J"}));
assertEquals(expected, bnames);
pdom.releaseReadLock();
}
public void testDummy() {}
}

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.IScope;
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.index.IIndex;
import org.eclipse.cdt.core.index.IndexFilter;
@ -201,12 +202,20 @@ public class CScope implements ICScope, IASTInternalScope {
if( o instanceof IBinding )
return (IBinding) o;
if( (resolve || ((IASTName)o).getBinding() != null) && ( o != name ) )
return ((IASTName)o).resolveBinding();
IASTName foundName= (IASTName) o;
if( (resolve || foundName.getBinding() != null) && ( foundName != name ) ) {
if(!isTypeDefinition(name) || CVisitor.declaredBefore(foundName, name)) {
return foundName.resolveBinding();
}
}
return null;
}
private boolean isTypeDefinition(IASTName name) {
return name.getPropertyInParent()==ICASTTypedefNameSpecifier.NAME;
}
/* (non-Javadoc)
* @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.IASTGotoStatement;
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.IASTLiteralExpression;
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.ObjectSet;
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.ProblemBinding;
import org.eclipse.core.runtime.CoreException;
@ -993,8 +995,11 @@ public class CVisitor {
} else if( node instanceof ICASTTypedefNameSpecifier ){
IASTNode blockItem = getContainingBlockItem( node );
try {
IBinding binding = (IBinding) findBinding( blockItem, ((ICASTTypedefNameSpecifier)node).getName(), bits );
if( binding instanceof IType )
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 )
return binding;
else if( binding != null )
return new ProblemBinding( node, IProblemBinding.SEMANTIC_INVALID_TYPE, binding.getNameCharArray() );
@ -1318,7 +1323,9 @@ public class CVisitor {
}
}
if( result != null ){
return ((IASTName)result).resolveBinding();
if(CVisitor.declaredBefore((IASTName)result, name)) {
return ((IASTName)result).resolveBinding();
}
}
}
if( (bits & CURRENT_SCOPE) == 0 )
@ -2031,4 +2038,42 @@ public class CVisitor {
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;
}
}