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:
parent
6760d0c61d
commit
75e338c2f8
6 changed files with 143 additions and 15 deletions
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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() {}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue