From c49ffa51b60edbf7f95951e3544e3bdaf34ed45a Mon Sep 17 00:00:00 2001 From: Andrew Niefer Date: Fri, 28 Jan 2005 20:56:18 +0000 Subject: [PATCH] C++: handle globally qualified qualified names "::a" : handle typedefs in base clauses C : handle nested structures --- .../tests/ast2/CompleteParser2Tests.java | 64 ++++++++++- .../internal/core/dom/parser/c/CVisitor.java | 105 ++++++++++-------- .../core/dom/parser/cpp/CPPSemantics.java | 20 ++-- 3 files changed, 133 insertions(+), 56 deletions(-) diff --git a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/CompleteParser2Tests.java b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/CompleteParser2Tests.java index 9ef70ccb1fe..3856ad1477f 100644 --- a/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/CompleteParser2Tests.java +++ b/core/org.eclipse.cdt.core.tests/parser/org/eclipse/cdt/core/parser/tests/ast2/CompleteParser2Tests.java @@ -100,7 +100,22 @@ public class CompleteParser2Tests extends TestCase { } public int size() { return nameList.size(); } } - + static protected class CNameCollector extends CVisitor.CBaseVisitorAction { + { + processNames = true; + } + public List nameList = new ArrayList(); + public int processName( IASTName name ){ + nameList.add( name ); + return PROCESS_CONTINUE; + } + public IASTName getName( int idx ){ + if( idx < 0 || idx >= nameList.size() ) + return null; + return (IASTName) nameList.get( idx ); + } + public int size() { return nameList.size(); } + } protected void assertInstances( CPPNameCollector nameCollector, IBinding binding, int num ) throws Exception { int count = 0; for( int i = 0; i < nameCollector.size(); i++ ) @@ -109,7 +124,14 @@ public class CompleteParser2Tests extends TestCase { assertEquals( count, num ); } - + protected void assertInstances( CNameCollector nameCollector, IBinding binding, int num ) throws Exception { + int count = 0; + for( int i = 0; i < nameCollector.size(); i++ ) + if( nameCollector.getName( i ).resolveBinding() == binding ) + count++; + + assertEquals( count, num ); + } protected IASTTranslationUnit parse(String code, boolean expectedToPass, ParserLanguage lang) throws Exception { return parse(code, expectedToPass, lang, false); @@ -1654,7 +1676,21 @@ public class CompleteParser2Tests extends TestCase { writer.write(" ::s outer = { 42 };"); //$NON-NLS-1$ writer.write("}"); //$NON-NLS-1$ - parse( writer.toString() ); + IASTTranslationUnit tu = parse( writer.toString() ); + + CPPNameCollector col = new CPPNameCollector(); + CPPVisitor.visitTranslationUnit( tu, col ); + + assertEquals( col.size(), 11 ); + + ICPPClassType s = (ICPPClassType) col.getName(0).resolveBinding(); + ICPPClassType s2 = (ICPPClassType) col.getName(3).resolveBinding(); + + ICPPClassType ref1 = (ICPPClassType) col.getName(5).resolveBinding(); + ICPPClassType ref2 = (ICPPClassType) col.getName( 9 ).resolveBinding(); + + assertSame( s, ref2 ); + assertSame( s2, ref1 ); } public void testBug57754() throws Exception @@ -1685,7 +1721,16 @@ public class CompleteParser2Tests extends TestCase { writer.write( "class G2 { int j; };"); //$NON-NLS-1$ writer.write( "typedef G2 AltG2;"); //$NON-NLS-1$ writer.write( "class AltG3 : AltG2 { int x;};"); //$NON-NLS-1$ - parse( writer.toString() ); + IASTTranslationUnit tu = parse( writer.toString() ); + CPPNameCollector col = new CPPNameCollector(); + CPPVisitor.visitTranslationUnit( tu, col ); + + assertEquals( col.size(), 7 ); + ICPPClassType G2 = (ICPPClassType) col.getName(0).resolveBinding(); + ITypedef alt = (ITypedef) col.getName(3).resolveBinding(); + + assertInstances( col, G2, 2 ); + assertInstances( col, alt, 2 ); } public void testBug46246() throws Exception @@ -1698,7 +1743,16 @@ public class CompleteParser2Tests extends TestCase { writer.write( "struct A a1; "); //$NON-NLS-1$ writer.write( "struct B b1; "); //$NON-NLS-1$ - parse( writer.toString(), true, ParserLanguage.C ); + IASTTranslationUnit tu = parse( writer.toString(), true, ParserLanguage.C ); + CNameCollector col = new CNameCollector(); + CVisitor.visitTranslationUnit( tu, col ); + + assertEquals( col.size(), 9 ); + ICompositeType A = (ICompositeType) col.getName(0).resolveBinding(); + ICompositeType B = (ICompositeType) col.getName(1).resolveBinding(); + + assertInstances( col, A, 2 ); + assertInstances( col, B, 2 ); } public void testBug45235() throws Exception diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java index eeac2bd3f35..d516544c5ff 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/c/CVisitor.java @@ -939,6 +939,7 @@ public class CVisitor { if( binding != null ) return binding; } + boolean typesOnly = (bits & TAGS) != 0; if( nodes != null ){ for( int i = 0; i < nodes.length; i++ ){ IASTNode node = nodes[i]; @@ -946,26 +947,20 @@ public class CVisitor { break; if( node instanceof IASTDeclarationStatement ){ IASTDeclarationStatement declStatement = (IASTDeclarationStatement) node; - binding = checkForBinding( declStatement.getDeclaration(), name ); + binding = checkForBinding( declStatement.getDeclaration(), name, typesOnly ); } else if( node instanceof IASTDeclaration ){ - binding = checkForBinding( (IASTDeclaration) node, name ); + binding = checkForBinding( (IASTDeclaration) node, name, typesOnly ); } if( binding != null ){ - if( (bits & TAGS) != 0 && !(binding instanceof ICompositeType || binding instanceof IEnumeration) || - (bits & TAGS) == 0 && (binding instanceof ICompositeType || binding instanceof IEnumeration) ) - { - binding = null; - } else { - return binding; - } + return binding; } } } else { //check the parent if( parent instanceof IASTDeclaration ){ - binding = checkForBinding( (IASTDeclaration) parent, name ); + binding = checkForBinding( (IASTDeclaration) parent, name, typesOnly ); } else if( parent instanceof IASTStatement ){ - binding = checkForBinding( (IASTStatement) parent, name ); + binding = checkForBinding( (IASTStatement) parent, name, typesOnly ); } if( binding != null ){ if( (bits & TAGS) != 0 && !(binding instanceof ICompositeType) || @@ -1008,49 +1003,71 @@ public class CVisitor { return external; } - private static IBinding checkForBinding( IASTDeclaration declaration, IASTName name ){ - if( declaration instanceof IASTSimpleDeclaration ){ - IASTSimpleDeclaration simpleDeclaration = (IASTSimpleDeclaration) declaration; - IASTDeclarator [] declarators = simpleDeclaration.getDeclarators(); - for( int i = 0; i < declarators.length; i++ ){ - IASTDeclarator declarator = declarators[i]; - IASTName declaratorName = declarator.getName(); - if( CharArrayUtils.equals( declaratorName.toCharArray(), name.toCharArray() ) ){ - return declaratorName.resolveBinding(); - } - } - - //decl spec - IASTDeclSpecifier declSpec = simpleDeclaration.getDeclSpecifier(); + private static IBinding checkForBinding( IASTDeclSpecifier declSpec, IASTName name, boolean typesOnly ){ + IASTName tempName = null; + if( typesOnly ){ if( declSpec instanceof ICASTElaboratedTypeSpecifier ){ - IASTName elabName = ((ICASTElaboratedTypeSpecifier)declSpec).getName(); - if( CharArrayUtils.equals( elabName.toCharArray(), name.toCharArray() ) ){ - return elabName.resolveBinding(); + tempName = ((ICASTElaboratedTypeSpecifier)declSpec).getName(); + if( CharArrayUtils.equals( tempName.toCharArray(), name.toCharArray() ) ){ + return tempName.resolveBinding(); } } else if( declSpec instanceof ICASTCompositeTypeSpecifier ){ - IASTName compName = ((ICASTCompositeTypeSpecifier)declSpec).getName(); - if( CharArrayUtils.equals( compName.toCharArray(), name.toCharArray() ) ){ - return compName.resolveBinding(); + tempName = ((ICASTCompositeTypeSpecifier)declSpec).getName(); + if( CharArrayUtils.equals( tempName.toCharArray(), name.toCharArray() ) ){ + return tempName.resolveBinding(); + } + //also have to check for any nested structs + IASTDeclaration [] nested = ((ICASTCompositeTypeSpecifier)declSpec).getMembers(); + for( int i = 0; i < nested.length; i++ ){ + if( nested[i] instanceof IASTSimpleDeclaration ){ + IASTDeclSpecifier d = ((IASTSimpleDeclaration)nested[i]).getDeclSpecifier(); + if( d instanceof ICASTCompositeTypeSpecifier ) { + IBinding temp = checkForBinding( d, name, typesOnly ); + if( temp != null ) + return temp; + } + } } } else if( declSpec instanceof ICASTEnumerationSpecifier ){ ICASTEnumerationSpecifier enumeration = (ICASTEnumerationSpecifier) declSpec; - IASTName eName = enumeration.getName(); - if( CharArrayUtils.equals( eName.toCharArray(), name.toCharArray() ) ){ - return eName.resolveBinding(); + tempName = enumeration.getName(); + if( CharArrayUtils.equals( tempName.toCharArray(), name.toCharArray() ) ){ + return tempName.resolveBinding(); } - //check enumerators too - IASTEnumerator [] list = enumeration.getEnumerators(); + } + } else { + if( declSpec instanceof ICASTEnumerationSpecifier ) { + //check enumerators + IASTEnumerator [] list = ((ICASTEnumerationSpecifier) declSpec).getEnumerators(); for( int i = 0; i < list.length; i++ ) { IASTEnumerator enumerator = list[i]; if( enumerator == null ) break; - eName = enumerator.getName(); - if( CharArrayUtils.equals( eName.toCharArray(), name.toCharArray() ) ){ - return eName.resolveBinding(); + tempName = enumerator.getName(); + if( CharArrayUtils.equals( tempName.toCharArray(), name.toCharArray() ) ){ + return tempName.resolveBinding(); } } - } - } else if( declaration instanceof IASTFunctionDefinition ){ + } + return null; + } + private static IBinding checkForBinding( IASTDeclaration declaration, IASTName name, boolean typesOnly ){ + IASTName tempName = null; + if( declaration instanceof IASTSimpleDeclaration ){ + IASTSimpleDeclaration simpleDeclaration = (IASTSimpleDeclaration) declaration; + + if( !typesOnly ){ + IASTDeclarator [] declarators = simpleDeclaration.getDeclarators(); + for( int i = 0; i < declarators.length; i++ ){ + IASTDeclarator declarator = declarators[i]; + tempName = declarator.getName(); + if( CharArrayUtils.equals( tempName.toCharArray(), name.toCharArray() ) ){ + return tempName.resolveBinding(); + } + } + } + return checkForBinding( simpleDeclaration.getDeclSpecifier(), name, typesOnly ); + } else if( !typesOnly && declaration instanceof IASTFunctionDefinition ){ IASTFunctionDefinition functionDef = (IASTFunctionDefinition) declaration; if (functionDef.getDeclarator() instanceof IASTStandardFunctionDeclarator) { @@ -1097,13 +1114,13 @@ public class CVisitor { return null; } - private static IBinding checkForBinding( IASTStatement statement, IASTName name ){ + private static IBinding checkForBinding( IASTStatement statement, IASTName name, boolean typesOnly ){ if( statement instanceof IASTDeclarationStatement ){ - return checkForBinding( ((IASTDeclarationStatement)statement).getDeclaration(), name ); + return checkForBinding( ((IASTDeclarationStatement)statement).getDeclaration(), name, typesOnly ); } else if( statement instanceof IASTForStatement ){ IASTForStatement forStatement = (IASTForStatement) statement; if( forStatement.getInitDeclaration() != null ){ - return checkForBinding( forStatement.getInitDeclaration(), name ); + return checkForBinding( forStatement.getInitDeclaration(), name, typesOnly ); } } return null; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java index dba89966b56..5f9e8bbd034 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/dom/parser/cpp/CPPSemantics.java @@ -77,6 +77,7 @@ import org.eclipse.cdt.core.dom.ast.cpp.ICPPNamespace; import org.eclipse.cdt.core.dom.ast.cpp.ICPPReferenceType; import org.eclipse.cdt.core.dom.ast.cpp.ICPPScope; import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier.ICPPASTBaseSpecifier; +import org.eclipse.cdt.core.parser.Keywords; import org.eclipse.cdt.core.parser.ast.IASTNamespaceDefinition; import org.eclipse.cdt.core.parser.util.CharArrayUtils; import org.eclipse.cdt.core.parser.util.ObjectMap; @@ -289,16 +290,13 @@ public class CPPSemantics { } } static protected IBinding resolveBinding( IASTName name ){ - if( name.toCharArray().length == 0 ){ + if( name.toCharArray().length == 2 && CharArrayUtils.equals( name.toCharArray(), Keywords.cpCOLONCOLON ) ){ IASTNode node = name.getParent(); if( node instanceof ICPPASTQualifiedName ){ ICPPASTQualifiedName qname = (ICPPASTQualifiedName) node; if( qname.getNames()[0] == name ){ //translation unit - while( ! (node instanceof ICPPASTTranslationUnit ) ){ - node = node.getParent(); - } - return ((ICPPASTTranslationUnit) node).resolveBinding(); + return ((ICPPASTTranslationUnit)node.getTranslationUnit()).resolveBinding(); } } return null; @@ -479,8 +477,16 @@ public class CPPSemantics { int size = bases.length; for( int i = 0; i < size; i++ ) { - ICPPClassType binding = (ICPPClassType) bases[i].getName().resolveBinding(); - ICPPClassScope parent = (ICPPClassScope) binding.getCompositeScope(); + ICPPClassType cls = null; + IBinding binding = bases[i].getName().resolveBinding(); + while( binding instanceof ITypedef && ((ITypedef)binding).getType() instanceof IBinding ){ + binding = (IBinding) ((ITypedef)binding).getType(); + } + if( binding instanceof ICPPClassType ) + cls = (ICPPClassType) binding; + else + continue; + ICPPClassScope parent = (ICPPClassScope) cls.getCompositeScope(); if( parent == null ) continue;