1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-09 10:46:02 +02:00

Patch for Andrew Niefer.

This patch changes the handling of ambiguities during prefix lookup.
It also addresses problems in the symbol table to do with qualified 
lookup.  Fixing these revealed problems caused by the 
CompleteParseASTFactory not always using the correct lookup functions.  So 
the factory has been modified to call the appropriate lookups.

The following tests have been created:
        FailedCompleteParseASTTest.testBug47926
        CompleteParseASTTest.testQualifiedLookup
        ParserSymbolTableTest.testPrefixLookup_Ambiguities
        ParserSymbolTableTest.testQualifiedUnqualifiedLookup
        FunctionMethodPatternTests.testLookupForDefinition
This commit is contained in:
John Camelon 2003-12-03 21:48:19 +00:00
parent 16459b510e
commit e43eb360d1
13 changed files with 417 additions and 114 deletions

View file

@ -1,3 +1,16 @@
2003-12-03 Andrew Niefer
-modified FailedCompleteParseASTTest.testPMDotStarPointerToMemberFunction_Bug43242
.testPMArrowStarPointerToMemberFunction_Bug43242
.testPMDotStar_bug43579
.testPMArrowStar_bug43579
-created: FailedCompleteParseASTTest.testBug47926
CompleteParseASTTest.testQualifiedLookup
ParserSymbolTableTest.testPrefixLookup_Ambiguities
ParserSymbolTableTest.testQualifiedUnqualifiedLookup
-modified resources/search/classDecl.cpp & include.h
-created FunctionMethodPatternTests.testLookupForDefinition
2003-11-27 Andrew Niefer 2003-11-27 Andrew Niefer
tests for Symbol table prefix lookup tests for Symbol table prefix lookup
ParserSymbolTableTest.testBug46882 ParserSymbolTableTest.testBug46882

View file

@ -45,35 +45,47 @@ public class FailedCompleteParseASTTest extends CompleteParseBaseTest
public void testPMDotStarPointerToMemberFunction_Bug43242() throws Exception public void testPMDotStarPointerToMemberFunction_Bug43242() throws Exception
{ {
Iterator i = parse ("class A { int m(int); }; \n A a; int A::*pm = &A::m; \n int f(){} \n int f(int); \n int x = f((a.*pm)(5));").getDeclarations(); //parse no longer passes
IASTClassSpecifier cl = (IASTClassSpecifier)((IASTAbstractTypeSpecifierDeclaration)i.next()).getTypeSpecifier(); try{
Iterator members = getDeclarations(cl); parse ("class A { int m(int); }; \n A a; int A::*pm = &A::m; \n int f(){} \n int f(int); \n int x = f((a.*pm)(5));");
IASTMethod method = (IASTMethod)members.next(); } catch ( ParserException e ){
IASTVariable a = (IASTVariable) i.next(); assertTrue( e.getMessage().equals( "FAILURE" ) );
IASTVariable pm = (IASTVariable) i.next(); }
IASTFunction f1 = (IASTFunction) i.next(); // Iterator i = parse ("class A { int m(int); }; \n A a; int A::*pm = &A::m; \n int f(){} \n int f(int); \n int x = f((a.*pm)(5));").getDeclarations();
IASTFunction f2 = (IASTFunction) i.next(); // IASTClassSpecifier cl = (IASTClassSpecifier)((IASTAbstractTypeSpecifierDeclaration)i.next()).getTypeSpecifier();
IASTVariable x = (IASTVariable) i.next(); // Iterator members = getDeclarations(cl);
// IASTMethod method = (IASTMethod)members.next();
assertAllReferences( 5 /* should be 8 */, // IASTVariable a = (IASTVariable) i.next();
createTaskList( new Task( cl, 2 /* should be 3 */ ), new Task( method ), new Task( a ), new Task( pm ) /* should be ,new Task( f2 ) */ // IASTVariable pm = (IASTVariable) i.next();
)); // IASTFunction f1 = (IASTFunction) i.next();
// IASTFunction f2 = (IASTFunction) i.next();
// IASTVariable x = (IASTVariable) i.next();
//
// assertAllReferences( 5 /* should be 8 */,
// createTaskList( new Task( cl, 2 /* should be 3 */ ), new Task( method ), new Task( a ), new Task( pm ) /* should be ,new Task( f2 ) */
// ));
} }
public void testPMArrowStarPointerToMemberFunction_Bug43242() throws Exception public void testPMArrowStarPointerToMemberFunction_Bug43242() throws Exception
{ {
Iterator i = parse ("class A { int m(int); }; \n A * a; int A::*pm = &A::m; \n int f(){} \n int f(int); \n int x = f((a->*pm)(5));").getDeclarations(); //parse no longer passes
IASTClassSpecifier cl = (IASTClassSpecifier)((IASTAbstractTypeSpecifierDeclaration)i.next()).getTypeSpecifier(); try{
Iterator members = getDeclarations(cl); parse ("class A { int m(int); }; \n A * a; int A::*pm = &A::m; \n int f(){} \n int f(int); \n int x = f((a->*pm)(5));");
IASTMethod method = (IASTMethod)members.next(); } catch ( ParserException e ){
IASTVariable a = (IASTVariable) i.next(); assertTrue( e.getMessage().equals( "FAILURE" ) );
IASTVariable pm = (IASTVariable) i.next(); }
IASTFunction f1 = (IASTFunction) i.next(); // Iterator i = parse ("class A { int m(int); }; \n A * a; int A::*pm = &A::m; \n int f(){} \n int f(int); \n int x = f((a->*pm)(5));").getDeclarations();
IASTFunction f2 = (IASTFunction) i.next(); // IASTClassSpecifier cl = (IASTClassSpecifier)((IASTAbstractTypeSpecifierDeclaration)i.next()).getTypeSpecifier();
IASTVariable x = (IASTVariable) i.next(); // Iterator members = getDeclarations(cl);
// IASTMethod method = (IASTMethod)members.next();
assertAllReferences( 5 /* should be more */, // IASTVariable a = (IASTVariable) i.next();
createTaskList( new Task( cl, 2 ), new Task( method ), new Task( a /*, 2 */), new Task( pm )/* ,new Task( f2 )*/)); // IASTVariable pm = (IASTVariable) i.next();
// IASTFunction f1 = (IASTFunction) i.next();
// IASTFunction f2 = (IASTFunction) i.next();
// IASTVariable x = (IASTVariable) i.next();
//
// assertAllReferences( 5 /* should be more */,
// createTaskList( new Task( cl, 2 ), new Task( method ), new Task( a /*, 2 */), new Task( pm )/* ,new Task( f2 )*/));
//
} }
public void testUnaryStarCastexpressionPointerToFunction_Bug43241() throws Exception public void testUnaryStarCastexpressionPointerToFunction_Bug43241() throws Exception
{ {
@ -93,29 +105,41 @@ public class FailedCompleteParseASTTest extends CompleteParseBaseTest
// Kind PM_DOTSTAR // Kind PM_DOTSTAR
public void testPMDotStar_bug43579() throws Exception public void testPMDotStar_bug43579() throws Exception
{ {
Iterator i = parse ("class A { int m; }; \n A a; int A::*pm; \n int f(){} \n int f(int); \n int x = f(a.*pm);").getDeclarations(); //parse no longer passes
IASTClassSpecifier cl = (IASTClassSpecifier)((IASTAbstractTypeSpecifierDeclaration)i.next()).getTypeSpecifier(); try{
IASTVariable a = (IASTVariable) i.next(); parse ( "class A { int m; }; \n A a; int A::*pm; \n int f(){} \n int f(int); \n int x = f(a.*pm);" );
IASTVariable pm = (IASTVariable) i.next(); } catch ( ParserException e ){
IASTFunction f1 = (IASTFunction) i.next(); assertTrue( e.getMessage().equals( "FAILURE" ) );
IASTFunction f2 = (IASTFunction) i.next(); }
IASTVariable x = (IASTVariable) i.next(); // Iterator i = parse ("class A { int m; }; \n A a; int A::*pm; \n int f(){} \n int f(int); \n int x = f(a.*pm);").getDeclarations();
assertFalse( i.hasNext() ); // IASTClassSpecifier cl = (IASTClassSpecifier)((IASTAbstractTypeSpecifierDeclaration)i.next()).getTypeSpecifier();
assertAllReferences( 4 /*should be 5 */, createTaskList( new Task( cl /* , 2 */ ), new Task( a), new Task( pm), new Task( f2))); // IASTVariable a = (IASTVariable) i.next();
// IASTVariable pm = (IASTVariable) i.next();
// IASTFunction f1 = (IASTFunction) i.next();
// IASTFunction f2 = (IASTFunction) i.next();
// IASTVariable x = (IASTVariable) i.next();
// assertFalse( i.hasNext() );
// assertAllReferences( 4 /*should be 5 */, createTaskList( new Task( cl /* , 2 */ ), new Task( a), new Task( pm), new Task( f2)));
} }
// Kind PM_ARROWSTAR // Kind PM_ARROWSTAR
public void testPMArrowStar_bug43579() throws Exception public void testPMArrowStar_bug43579() throws Exception
{ {
Iterator i = parse ("class A { int m; }; \n A * a; int A::*pm; \n int f(){} \n int f(int); \n int x = f(a->*pm);").getDeclarations(); //parse no longer passes
IASTClassSpecifier cl = (IASTClassSpecifier)((IASTAbstractTypeSpecifierDeclaration)i.next()).getTypeSpecifier(); try{
IASTVariable a = (IASTVariable) i.next(); parse ("class A { int m; }; \n A * a; int A::*pm; \n int f(){} \n int f(int); \n int x = f(a->*pm);");
IASTVariable pm = (IASTVariable) i.next(); } catch ( ParserException e ){
IASTFunction f1 = (IASTFunction) i.next(); assertTrue( e.getMessage().equals( "FAILURE" ) );
IASTFunction f2 = (IASTFunction) i.next(); }
IASTVariable x = (IASTVariable) i.next(); // Iterator i = parse ("class A { int m; }; \n A * a; int A::*pm; \n int f(){} \n int f(int); \n int x = f(a->*pm);").getDeclarations();
assertFalse( i.hasNext() ); // IASTClassSpecifier cl = (IASTClassSpecifier)((IASTAbstractTypeSpecifierDeclaration)i.next()).getTypeSpecifier();
assertAllReferences( 4 /*should be 5 */, createTaskList( new Task( cl /* , 2 */ ), new Task( a), new Task( pm), new Task( f2))); // IASTVariable a = (IASTVariable) i.next();
// IASTVariable pm = (IASTVariable) i.next();
// IASTFunction f1 = (IASTFunction) i.next();
// IASTFunction f2 = (IASTFunction) i.next();
// IASTVariable x = (IASTVariable) i.next();
// assertFalse( i.hasNext() );
// assertAllReferences( 4 /*should be 5 */, createTaskList( new Task( cl /* , 2 */ ), new Task( a), new Task( pm), new Task( f2)));
} }
public void testErrorHandling_1() throws Exception public void testErrorHandling_1() throws Exception
@ -150,4 +174,25 @@ public class FailedCompleteParseASTTest extends CompleteParseBaseTest
} }
public void testBug47926() throws Exception{
StringBuffer buffer = new StringBuffer();
buffer.append( "void f () {} \n" );
buffer.append( "class A { }; \n" );
buffer.append( "void main() { A * a = new A(); a->f(); } ");
Iterator i = parse( buffer.toString() ).getDeclarations();
IASTFunction f = (IASTFunction) i.next();
IASTClassSpecifier classA = (IASTClassSpecifier)((IASTAbstractTypeSpecifierDeclaration)i.next()).getTypeSpecifier();
IASTFunction main = (IASTFunction) i.next();
Iterator fnIter = getDeclarations( main );
IASTVariable a = (IASTVariable) fnIter.next();
//there should be no reference to f, but there is
//assertAllReferences( 3, createTaskList( new Task( classA, 2 ), new Task( a ) ) );
assertAllReferences( 4, createTaskList( new Task( classA, 2 ), new Task( a ), new Task( f ) ) );
}
} }

View file

@ -1074,4 +1074,32 @@ public class CompleteParseASTTest extends CompleteParseBaseTest
assertAllReferences( 1, createTaskList( new Task( structS ) ) ); assertAllReferences( 1, createTaskList( new Task( structS ) ) );
assertFalse( i.hasNext() ); assertFalse( i.hasNext() );
} }
public void testQualifiedLookup() throws Exception{
//this is meant to test that on a->f, the lookup for f is qualified
//the namespace is necessary because of bug 47926
StringBuffer buffer = new StringBuffer();
buffer.append( "namespace N {" );
buffer.append( " void f () {} \n" );
buffer.append( " class A { }; \n" );
buffer.append( "}" );
buffer.append( "void main() { N::A * a = new N::A(); a->f(); } ");
Iterator i = parse( buffer.toString() ).getDeclarations();
IASTNamespaceDefinition namespace = (IASTNamespaceDefinition) i.next();
Iterator nsIter = getDeclarations( namespace );
IASTFunction f = (IASTFunction) nsIter.next();
IASTClassSpecifier classA = (IASTClassSpecifier)((IASTAbstractTypeSpecifierDeclaration)nsIter.next()).getTypeSpecifier();
assertFalse( nsIter.hasNext() );
IASTFunction main = (IASTFunction) i.next();
Iterator fnIter = getDeclarations( main );
IASTVariable a = (IASTVariable) fnIter.next();
assertAllReferences( 5, createTaskList( new Task( namespace, 2 ), new Task( classA, 2 ), new Task( a ) ) );
}
} }

View file

@ -1950,10 +1950,10 @@ public class ParserSymbolTableTest extends TestCase {
B.setType( TypeInfo.t_namespace ); B.setType( TypeInfo.t_namespace );
mark = table.setMark(); mark = table.setMark();
A.addUsingDirective( B ); C.addUsingDirective( B );
assertEquals( A.getUsingDirectives().size(), 1 ); assertEquals( C.getUsingDirectives().size(), 1 );
table.rollBack( mark ); table.rollBack( mark );
assertEquals( A.getUsingDirectives().size(), 0 ); assertEquals( C.getUsingDirectives().size(), 0 );
} }
/** /**
@ -3107,5 +3107,93 @@ public class ParserSymbolTableTest extends TestCase {
assertTrue( results.contains( af2 ) ); assertTrue( results.contains( af2 ) );
} }
/**
* int aa;
* namespace {
* namespace U {
* int a;
* }
* namespace V{
* int a;
* }
* namespace W{
* int a;
* }
*
* void f(){
* using namespace U;
* using namespace V;
* using namespace W;
* a(CTRL+SPACE)
* }
* }
*
* @throws Exception
*/
public void testPrefixLookup_Ambiguities() throws Exception{
newTable();
ISymbol aa = table.newSymbol( "aa", TypeInfo.t_int );
table.getCompilationUnit().addSymbol( aa );
IContainerSymbol ns = table.newContainerSymbol( "", TypeInfo.t_namespace );
table.getCompilationUnit().addSymbol( ns );
IContainerSymbol U = table.newContainerSymbol( "U", TypeInfo.t_namespace );
ns.addSymbol( U );
ISymbol a1 = table.newSymbol( "a", TypeInfo.t_int );
U.addSymbol( a1 );
IContainerSymbol V = table.newContainerSymbol( "V", TypeInfo.t_namespace );
ns.addSymbol( V );
ISymbol a2 = table.newSymbol( "a", TypeInfo.t_int );
V.addSymbol( a2 );
IContainerSymbol W = table.newContainerSymbol( "W", TypeInfo.t_namespace );
ns.addSymbol( W );
ISymbol a3 = table.newSymbol( "a", TypeInfo.t_int );
W.addSymbol( a3 );
IParameterizedSymbol f = table.newParameterizedSymbol( "f", TypeInfo.t_function );
ns.addSymbol( f );
f.addUsingDirective( U );
f.addUsingDirective( V );
f.addUsingDirective( W );
List results = f.prefixLookup( TypeInfo.t_any, "a", false );
assertTrue( results != null );
assertEquals( results.size(), 1 );
assertTrue( results.contains( aa ) );
}
/**
* int i;
* class A {
* void g(){
* A a;
* a.i++; //fail qualified lookup, no i in A
* i++; //success unqualified lookup
* }
* };
*
* @throws Exception
*/
public void testQualifiedUnqualifiedLookup() throws Exception{
newTable();
ISymbol i = table.newSymbol( "i", TypeInfo.t_int );
table.getCompilationUnit().addSymbol( i );
IDerivableContainerSymbol A = table.newDerivableContainerSymbol( "A", TypeInfo.t_class );
table.getCompilationUnit().addSymbol( A );
IParameterizedSymbol g = table.newParameterizedSymbol( "g", TypeInfo.t_function );
A.addSymbol( g );
assertEquals( null, A.qualifiedLookup( "i" ) );
assertEquals( i, g.lookup( "i" ) );
}
} }

View file

@ -28,9 +28,13 @@ namespace NS {
Three Three
}; };
using namespace NS2; void f(){
using namespace NS2;
a aStruct;
}
a aStruct;
AA anotherStruct; AA anotherStruct;
}; };
union u{ } ; union u{ } ;

View file

@ -25,4 +25,10 @@ class DeclsAndDefns{
void forwardFunction(); void forwardFunction();
class Direction{
void turn();
};
class Right : public Direction {
void turn() { }
};
#endif #endif

View file

@ -191,4 +191,16 @@ public class FunctionMethodPatternTests extends BaseSearchTest {
matches = resultCollector.getSearchResults(); matches = resultCollector.getSearchResults();
assertEquals( matches.size(), 1 ); assertEquals( matches.size(), 1 );
} }
public void testLookupForDefinition(){
ICSearchPattern pattern = SearchEngine.createSearchPattern( "turn", METHOD, DECLARATIONS, true );
search( workspace, pattern, scope, resultCollector );
Set matches = resultCollector.getSearchResults();
assertEquals( matches.size(), 2 );
pattern = SearchEngine.createSearchPattern( "Direction::turn", METHOD, DEFINITIONS, true );
search( workspace, pattern, scope, resultCollector );
matches = resultCollector.getSearchResults();
assertEquals( matches.size(), 0 );
}
} }

View file

@ -148,7 +148,7 @@ public class OtherPatternTests extends BaseSearchTest {
search( workspace, pattern, scope, resultCollector ); search( workspace, pattern, scope, resultCollector );
Set matches = resultCollector.getSearchResults(); Set matches = resultCollector.getSearchResults();
assertEquals( matches.size(), 2 ); assertEquals( matches.size(), 1 );
IMatch match = (IMatch) matches.iterator().next(); IMatch match = (IMatch) matches.iterator().next();
assertTrue( match.getParentName().equals( "NS::B" ) ); assertTrue( match.getParentName().equals( "NS::B" ) );
@ -185,7 +185,7 @@ public class OtherPatternTests extends BaseSearchTest {
search( workspace, orPattern, scope, resultCollector ); search( workspace, orPattern, scope, resultCollector );
matches = resultCollector.getSearchResults(); matches = resultCollector.getSearchResults();
assertEquals( matches.size(), 6 ); assertEquals( matches.size(), 5 );
} }
public void testMacroPattern(){ public void testMacroPattern(){

View file

@ -1,3 +1,11 @@
2003-12-03 Andrew Niefer
- Symbol table - modify prefix lookup handling of ambiguities
- fix up qualified lookup
- add IContainerSymbol.lookupMethodForDefinition
- Parser - modify Complete parse AST factory to use the correct lookups in different situations
- Created a LookupType enum to specify what kind of lookup is needed (Qualified, unqualified, for definition)
2003-11-27 Andrew Niefer 2003-11-27 Andrew Niefer
fix bug 47264: Parse fails when using struct s foo; and int s; in function bodies fix bug 47264: Parse fails when using struct s foo; and int s; in function bodies

View file

@ -16,6 +16,7 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import org.eclipse.cdt.core.parser.Enum;
import org.eclipse.cdt.core.parser.IToken; import org.eclipse.cdt.core.parser.IToken;
import org.eclipse.cdt.core.parser.ITokenDuple; import org.eclipse.cdt.core.parser.ITokenDuple;
import org.eclipse.cdt.core.parser.ParserLanguage; import org.eclipse.cdt.core.parser.ParserLanguage;
@ -101,6 +102,17 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto
SUBSCRIPT.add( TypeInfo.OperatorExpression.subscript ); SUBSCRIPT.add( TypeInfo.OperatorExpression.subscript );
} }
static private class LookupType extends Enum {
public static final LookupType QUALIFIED = new LookupType( 1 );
public static final LookupType UNQUALIFIED = new LookupType( 2 );
public static final LookupType FORDEFINITION = new LookupType( 3 );
private LookupType( int constant)
{
super( constant );
}
}
public CompleteParseASTFactory( ParserLanguage language ) public CompleteParseASTFactory( ParserLanguage language )
{ {
super(); super();
@ -146,7 +158,7 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto
return true; return true;
} }
private ISymbol lookupElement (IContainerSymbol startingScope, String name, TypeInfo.eType type, List parameters) throws ParserSymbolTableException{ private ISymbol lookupElement (IContainerSymbol startingScope, String name, TypeInfo.eType type, List parameters, LookupType lookupType ) throws ParserSymbolTableException{
ISymbol result = null; ISymbol result = null;
try { try {
if((type == TypeInfo.t_function) || (type == TypeInfo.t_constructor)){ if((type == TypeInfo.t_function) || (type == TypeInfo.t_constructor)){
@ -156,13 +168,24 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto
IDerivableContainerSymbol startingDerivableScope = (IDerivableContainerSymbol) startingScope; IDerivableContainerSymbol startingDerivableScope = (IDerivableContainerSymbol) startingScope;
result = startingDerivableScope.lookupConstructor( new LinkedList(parameters)); result = startingDerivableScope.lookupConstructor( new LinkedList(parameters));
} }
else else {
result = startingScope.qualifiedFunctionLookup(name, new LinkedList(parameters)); if( lookupType == LookupType.QUALIFIED )
result = startingScope.qualifiedFunctionLookup(name, new LinkedList(parameters));
else if( lookupType == LookupType.UNQUALIFIED )
result = startingScope.unqualifiedFunctionLookup( name, new LinkedList( parameters ) );
else
result = startingScope.lookupMethodForDefinition( name, new LinkedList( parameters ) );
}
else else
result = null; result = null;
}else{ }else{
// looking for something else // looking for something else
result = startingScope.qualifiedLookup(name, type); if( lookupType == LookupType.QUALIFIED )
result = startingScope.qualifiedLookup(name, type);
else if( lookupType == LookupType.UNQUALIFIED )
result = startingScope.elaboratedLookup( type, name );
else
result = startingScope.lookupMemberForDefinition( name );
} }
} catch (ParserSymbolTableException e) { } catch (ParserSymbolTableException e) {
if( e.reason != ParserSymbolTableException.r_UnableToResolveFunction ) if( e.reason != ParserSymbolTableException.r_UnableToResolveFunction )
@ -171,11 +194,11 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto
return result; return result;
} }
protected ISymbol lookupQualifiedName( IContainerSymbol startingScope, String name, List references, boolean throwOnError ) throws ASTSemanticException{ protected ISymbol lookupQualifiedName( IContainerSymbol startingScope, String name, List references, boolean throwOnError, LookupType lookup ) throws ASTSemanticException{
return lookupQualifiedName(startingScope, name, TypeInfo.t_any, null, 0, references, throwOnError); return lookupQualifiedName(startingScope, name, TypeInfo.t_any, null, 0, references, throwOnError, lookup );
} }
protected ISymbol lookupQualifiedName( IContainerSymbol startingScope, String name, TypeInfo.eType type, List parameters, int offset, List references, boolean throwOnError ) throws ASTSemanticException protected ISymbol lookupQualifiedName( IContainerSymbol startingScope, String name, TypeInfo.eType type, List parameters, int offset, List references, boolean throwOnError, LookupType lookup ) throws ASTSemanticException
{ {
ISymbol result = null; ISymbol result = null;
try try
@ -183,7 +206,7 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto
if( name == null ) throw new ASTSemanticException(); if( name == null ) throw new ASTSemanticException();
try try
{ {
result = lookupElement(startingScope, name, type, parameters); result = lookupElement(startingScope, name, type, parameters, lookup);
if( result != null ) if( result != null )
addReference(references, createReference( result, name, offset )); addReference(references, createReference( result, name, offset ));
else else
@ -206,10 +229,16 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto
} }
protected ISymbol lookupQualifiedName( IContainerSymbol startingScope, ITokenDuple name, List references, boolean throwOnError ) throws ASTSemanticException{ protected ISymbol lookupQualifiedName( IContainerSymbol startingScope, ITokenDuple name, List references, boolean throwOnError ) throws ASTSemanticException{
return lookupQualifiedName(startingScope, name, TypeInfo.t_any, null, references, throwOnError); return lookupQualifiedName(startingScope, name, references, throwOnError, LookupType.UNQUALIFIED);
} }
protected ISymbol lookupQualifiedName( IContainerSymbol startingScope, ITokenDuple name, List references, boolean throwOnError, LookupType lookup ) throws ASTSemanticException{
protected ISymbol lookupQualifiedName( IContainerSymbol startingScope, ITokenDuple name, TypeInfo.eType type, List parameters, List references, boolean throwOnError ) throws ASTSemanticException return lookupQualifiedName(startingScope, name, TypeInfo.t_any, null, references, throwOnError, lookup );
}
protected ISymbol lookupQualifiedName( IContainerSymbol startingScope, ITokenDuple name, TypeInfo.eType type, List parameters, List references, boolean throwOnError ) throws ASTSemanticException{
return lookupQualifiedName( startingScope, name, type, parameters, references, throwOnError, LookupType.UNQUALIFIED );
}
protected ISymbol lookupQualifiedName( IContainerSymbol startingScope, ITokenDuple name, TypeInfo.eType type, List parameters, List references, boolean throwOnError, LookupType lookup ) throws ASTSemanticException
{ {
ISymbol result = null; ISymbol result = null;
IToken firstSymbol = null; IToken firstSymbol = null;
@ -226,7 +255,7 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto
firstSymbol = name.getFirstToken(); firstSymbol = name.getFirstToken();
try try
{ {
result = lookupElement(startingScope, firstSymbol.getImage(), type, parameters); result = lookupElement(startingScope, firstSymbol.getImage(), type, parameters, lookup );
if( result != null ) if( result != null )
addReference( references, createReference( result, firstSymbol.getImage(), firstSymbol.getOffset() )); addReference( references, createReference( result, firstSymbol.getImage(), firstSymbol.getOffset() ));
else else
@ -252,7 +281,7 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto
try try
{ {
if( t == name.getLastToken() ) if( t == name.getLastToken() )
result = lookupElement((IContainerSymbol)result, t.getImage(), type, parameters); result = lookupElement((IContainerSymbol)result, t.getImage(), type, parameters, ( lookup == LookupType.FORDEFINITION ) ? lookup : LookupType.QUALIFIED );
else else
result = ((IContainerSymbol)result).lookupNestedNameSpecifier( t.getImage() ); result = ((IContainerSymbol)result).lookupNestedNameSpecifier( t.getImage() );
addReference( references, createReference( result, t.getImage(), t.getOffset() )); addReference( references, createReference( result, t.getImage(), t.getOffset() ));
@ -814,7 +843,7 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto
// If the expression is lookup symbol if it is in the scope of a type after a "." or an "->" // If the expression is lookup symbol if it is in the scope of a type after a "." or an "->"
IContainerSymbol searchScope = getSearchScope(kind, lhs, startingScope); IContainerSymbol searchScope = getSearchScope(kind, lhs, startingScope);
if (!searchScope.equals(startingScope)) if (!searchScope.equals(startingScope))
symbol = lookupQualifiedName(searchScope, ((ASTExpression)rhs).getIdExpressionTokenDuple(), references, false); symbol = lookupQualifiedName(searchScope, ((ASTExpression)rhs).getIdExpressionTokenDuple(), references, false, LookupType.QUALIFIED );
// get symbol if it is the "this" pointer // get symbol if it is the "this" pointer
// go up the scope until you hit a class // go up the scope until you hit a class
@ -839,7 +868,10 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto
parameters = new ArrayList(); parameters = new ArrayList();
parameters.add(expResult.getResult()); parameters.add(expResult.getResult());
} }
symbol = lookupQualifiedName(functionScope, functionId, TypeInfo.t_function, parameters, references, false); if( functionScope.equals( startingScope ) )
symbol = lookupQualifiedName(functionScope, functionId, TypeInfo.t_function, parameters, references, false);
else
symbol = lookupQualifiedName(functionScope, functionId, TypeInfo.t_function, parameters, references, false, LookupType.QUALIFIED );
} }
return symbol; return symbol;
@ -1634,7 +1666,7 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto
IParameterizedSymbol functionDeclaration = null; IParameterizedSymbol functionDeclaration = null;
functionDeclaration = functionDeclaration =
(IParameterizedSymbol) lookupQualifiedName(ownerScope, name.getLastToken().getImage(), TypeInfo.t_function, functionParameters, 0, new ArrayList(), false); (IParameterizedSymbol) lookupQualifiedName(ownerScope, name.getLastToken().getImage(), TypeInfo.t_function, functionParameters, 0, new ArrayList(), false, LookupType.UNQUALIFIED );
if( functionDeclaration != null ) if( functionDeclaration != null )
{ {
@ -1935,8 +1967,8 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto
List functionReferences = new ArrayList(); List functionReferences = new ArrayList();
functionDeclaration = functionDeclaration =
(IParameterizedSymbol) lookupQualifiedName(ownerScope, name, isConstructor ? TypeInfo.t_constructor : TypeInfo.t_function, functionParameters, 0, functionReferences, false); (IParameterizedSymbol) lookupQualifiedName(ownerScope, name, isConstructor ? TypeInfo.t_constructor : TypeInfo.t_function, functionParameters, 0, functionReferences, false, LookupType.FORDEFINITION );
if( functionDeclaration != null ) if( functionDeclaration != null )
{ {
previouslyDeclared = true; previouslyDeclared = true;
@ -1994,7 +2026,8 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto
ASTConstructorMemberInitializer realInitializer = ((ASTConstructorMemberInitializer)initializer); ASTConstructorMemberInitializer realInitializer = ((ASTConstructorMemberInitializer)initializer);
try try
{ {
lookupQualifiedName( symbol, initializer.getName(), realInitializer.getNameOffset(), realInitializer.getReferences(), false ); IDerivableContainerSymbol container = (IDerivableContainerSymbol) symbol.getContainingSymbol();
lookupQualifiedName(container, initializer.getName(), TypeInfo.t_any, null, realInitializer.getNameOffset(), realInitializer.getReferences(), false, LookupType.QUALIFIED);
} }
catch( ASTSemanticException ase ) catch( ASTSemanticException ase )
{ {
@ -2009,19 +2042,6 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto
} }
/**
* @param symbol
* @param string
* @param i
* @param list
* @param b
* @return
*/
protected ISymbol lookupQualifiedName(IParameterizedSymbol startingScope, String name, int nameOffset, List references, boolean throwOnError) throws ASTSemanticException
{
return lookupQualifiedName(startingScope, name, TypeInfo.t_any, null, nameOffset, references, throwOnError);
}
/** /**
* @param symbol * @param symbol
* @param isConst * @param isConst
@ -2080,17 +2100,16 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto
Iterator i = tokens.iterator(); Iterator i = tokens.iterator();
while (i.hasNext() && (numOfTokens++) < tokens.size()){ while (i.hasNext() && (numOfTokens++) < tokens.size()){
String token = (String) i.next(); String token = (String) i.next();
IContainerSymbol parentSymbol =
(IContainerSymbol) lookupQualifiedName(parentScope, token, TypeInfo.t_class, null, offset, references, false); IContainerSymbol parentSymbol = null;
if(parentSymbol == null){ try {
parentSymbol = (IContainerSymbol) lookupQualifiedName(parentScope, token, TypeInfo.t_namespace, null, offset, references, false); parentSymbol = (IContainerSymbol) parentScope.lookupNestedNameSpecifier( token );
} if( parentSymbol != null )
if(parentSymbol == null){ addReference( references, createReference( parentSymbol, name, offset ));
parentSymbol = (IContainerSymbol) lookupQualifiedName(parentScope, token, TypeInfo.t_struct, null, offset, references, false); } catch (ParserSymbolTableException e1) {
} //do nothing
if(parentSymbol == null){
parentSymbol = (IContainerSymbol) lookupQualifiedName(parentScope, token, TypeInfo.t_union, null, offset, references, false);
} }
if(parentSymbol == null) if(parentSymbol == null)
break; break;
else { else {
@ -2124,7 +2143,7 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto
newSymbol.setIsForwardDeclaration(isStatic); newSymbol.setIsForwardDeclaration(isStatic);
boolean previouslyDeclared = false; boolean previouslyDeclared = false;
if(!isStatic){ if(!isStatic){
ISymbol variableDeclaration = (ISymbol) lookupQualifiedName(ownerScope, name, new ArrayList(), false); ISymbol variableDeclaration = (ISymbol) lookupQualifiedName(ownerScope, name, new ArrayList(), false, LookupType.UNQUALIFIED);
if( variableDeclaration != null ) if( variableDeclaration != null )
{ {
@ -2331,7 +2350,7 @@ public class CompleteParseASTFactory extends BaseASTFactory implements IASTFacto
boolean previouslyDeclared = false; boolean previouslyDeclared = false;
if(!isStatic){ if(!isStatic){
List fieldReferences = new ArrayList(); List fieldReferences = new ArrayList();
ISymbol fieldDeclaration = lookupQualifiedName(ownerScope, name, fieldReferences, false); ISymbol fieldDeclaration = lookupQualifiedName(ownerScope, name, fieldReferences, false, LookupType.FORDEFINITION);
if( fieldDeclaration != null ) if( fieldDeclaration != null )
{ {

View file

@ -158,6 +158,10 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol {
if( namespace.getType() != TypeInfo.t_namespace ){ if( namespace.getType() != TypeInfo.t_namespace ){
throw new ParserSymbolTableException( ParserSymbolTableException.r_InvalidUsing ); throw new ParserSymbolTableException( ParserSymbolTableException.r_InvalidUsing );
} }
//7.3.4 A using-directive shall not appear in class scope
if( isType( TypeInfo.t_class, TypeInfo.t_union ) ){
throw new ParserSymbolTableException( ParserSymbolTableException.r_InvalidUsing );
}
//handle namespace aliasing //handle namespace aliasing
ISymbol alias = namespace.getTypeSymbol(); ISymbol alias = namespace.getTypeSymbol();
@ -334,6 +338,26 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol {
return ParserSymbolTable.resolveAmbiguities( data ); return ParserSymbolTable.resolveAmbiguities( data );
} }
public IParameterizedSymbol lookupMethodForDefinition( String name, List parameters ) throws ParserSymbolTableException{
LookupData data = new LookupData( name, TypeInfo.t_any, getTemplateInstance() );
data.qualified = true;
data.parameters = ( parameters == null ) ? new LinkedList() : parameters;
IContainerSymbol container = this;
//handle namespace aliases
if( container.isType( TypeInfo.t_namespace ) ){
ISymbol symbol = container.getTypeSymbol();
if( symbol != null && symbol.isType( TypeInfo.t_namespace ) ){
container = (IContainerSymbol) symbol;
}
}
data.foundItems = ParserSymbolTable.lookupInContained( data, container );
ISymbol symbol = ParserSymbolTable.resolveAmbiguities( data );
return (IParameterizedSymbol) (( symbol instanceof IParameterizedSymbol ) ? symbol : null);
}
/* (non-Javadoc) /* (non-Javadoc)
* @see org.eclipse.cdt.internal.core.parser.pst.IContainerSymbol#lookupNestedNameSpecifier(java.lang.String) * @see org.eclipse.cdt.internal.core.parser.pst.IContainerSymbol#lookupNestedNameSpecifier(java.lang.String)
*/ */
@ -479,6 +503,7 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol {
if( associated.contains( associatedScope ) ){ if( associated.contains( associatedScope ) ){
data.qualified = true; data.qualified = true;
data.ignoreUsingDirectives = true; data.ignoreUsingDirectives = true;
data.usingDirectivesOnly = false;
ParserSymbolTable.lookup( data, associatedScope ); ParserSymbolTable.lookup( data, associatedScope );
} }
} }
@ -556,6 +581,14 @@ public class ContainerSymbol extends BasicSymbol implements IContainerSymbol {
if( data.foundItems == null || data.foundItems.isEmpty() ){ if( data.foundItems == null || data.foundItems.isEmpty() ){
return null; return null;
} else { } else {
//remove any ambiguous symbols
if( data.ambiguities != null && !data.ambiguities.isEmpty() ){
Iterator iter = data.ambiguities.iterator();
while( iter.hasNext() ){
data.foundItems.remove( iter.next() );
}
}
List list = new LinkedList(); List list = new LinkedList();
Iterator iter = data.foundItems.keySet().iterator(); Iterator iter = data.foundItems.keySet().iterator();

View file

@ -44,6 +44,7 @@ public interface IContainerSymbol extends ISymbol {
public ISymbol elaboratedLookup( TypeInfo.eType type, String name ) throws ParserSymbolTableException; public ISymbol elaboratedLookup( TypeInfo.eType type, String name ) throws ParserSymbolTableException;
public ISymbol lookup( String name ) throws ParserSymbolTableException; public ISymbol lookup( String name ) throws ParserSymbolTableException;
public ISymbol lookupMemberForDefinition( String name ) throws ParserSymbolTableException; public ISymbol lookupMemberForDefinition( String name ) throws ParserSymbolTableException;
public IParameterizedSymbol lookupMethodForDefinition( String name, List parameters ) throws ParserSymbolTableException;
public IContainerSymbol lookupNestedNameSpecifier( String name ) throws ParserSymbolTableException; public IContainerSymbol lookupNestedNameSpecifier( String name ) throws ParserSymbolTableException;
public ISymbol qualifiedLookup( String name ) throws ParserSymbolTableException; public ISymbol qualifiedLookup( String name ) throws ParserSymbolTableException;
public ISymbol qualifiedLookup( String name, TypeInfo.eType t ) throws ParserSymbolTableException; public ISymbol qualifiedLookup( String name, TypeInfo.eType t ) throws ParserSymbolTableException;

View file

@ -106,11 +106,14 @@ public class ParserSymbolTable {
LinkedList transitives = new LinkedList(); //list of transitive using directives LinkedList transitives = new LinkedList(); //list of transitive using directives
//if this name define in this scope? //if this name define in this scope?
Map map = lookupInContained( data, inSymbol ); Map map = null;
if( data.foundItems == null || data.foundItems.isEmpty() ){ if( !data.usingDirectivesOnly ){
data.foundItems = map; map = lookupInContained( data, inSymbol );
} else { if( data.foundItems == null || data.foundItems.isEmpty() ){
mergeResults( data, data.foundItems, map ); data.foundItems = map;
} else {
mergeResults( data, data.foundItems, map );
}
} }
if( inSymbol.getSymbolTable().getLanguage() == ParserLanguage.CPP && if( inSymbol.getSymbolTable().getLanguage() == ParserLanguage.CPP &&
@ -149,7 +152,7 @@ public class ParserSymbolTable {
return; return;
} }
if( inSymbol instanceof IDerivableContainerSymbol ){ if( !data.usingDirectivesOnly && inSymbol instanceof IDerivableContainerSymbol ){
//if we still havn't found it, check any parents we have //if we still havn't found it, check any parents we have
data.visited.clear(); //each virtual base class is searched at most once data.visited.clear(); //each virtual base class is searched at most once
map = lookupInParents( data, (IDerivableContainerSymbol)inSymbol ); map = lookupInParents( data, (IDerivableContainerSymbol)inSymbol );
@ -162,10 +165,19 @@ public class ParserSymbolTable {
} }
//if still not found, check our containing scope. //if still not found, check our containing scope.
if( ( data.foundItems == null || data.foundItems.isEmpty() || ( data.mode == LookupMode.PREFIX && !data.qualified ) ) if( ( data.foundItems == null || data.foundItems.isEmpty() || data.mode == LookupMode.PREFIX )
&& inSymbol.getContainingSymbol() != null ) && inSymbol.getContainingSymbol() != null )
{ {
lookup( data, inSymbol.getContainingSymbol() ); if( data.qualified ){
if( data.usingDirectives != null && !data.usingDirectives.isEmpty() ){
data.usingDirectivesOnly = true;
lookup( data, inSymbol.getContainingSymbol() );
}
} else {
lookup( data, inSymbol.getContainingSymbol() );
}
} }
return; return;
@ -393,7 +405,14 @@ public class ParserSymbolTable {
} else if( foundSymbol.getTypeInfo().isForwardDeclaration() && foundSymbol.getTypeSymbol() == cls ){ } else if( foundSymbol.getTypeInfo().isForwardDeclaration() && foundSymbol.getTypeSymbol() == cls ){
//decl is a forward declaration of cls, we already have what we want (cls) //decl is a forward declaration of cls, we already have what we want (cls)
} else { } else {
throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous ); if( data.mode == LookupMode.PREFIX ){
if( data.ambiguities == null ){
data.ambiguities = new HashSet();
}
data.ambiguities.add( foundSymbol.getName() );
} else {
throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
}
} }
} }
} else { } else {
@ -401,7 +420,14 @@ public class ParserSymbolTable {
if( obj == null ){ if( obj == null ){
obj = foundSymbol; obj = foundSymbol;
} else { } else {
throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous ); if( data.mode == LookupMode.PREFIX ){
if( data.ambiguities == null ){
data.ambiguities = new HashSet();
}
data.ambiguities.add( foundSymbol.getName() );
} else {
throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
}
} }
} }
} }
@ -447,10 +473,17 @@ public class ParserSymbolTable {
} }
if( ambiguous ){ if( ambiguous ){
throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous ); if( data.mode == LookupMode.PREFIX ){
} else { if( data.ambiguities == null ){
return cls; data.ambiguities = new HashSet();
} }
data.ambiguities.add( foundSymbol.getName() );
} else {
throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
}
}
return cls;
} }
/** /**
* *
@ -546,7 +579,17 @@ public class ParserSymbolTable {
while( iter.hasNext() ){ while( iter.hasNext() ){
key = iter.next(); key = iter.next();
if( symbol.containsKey( key ) ){ if( symbol.containsKey( key ) ){
checkAmbiguity( symbol.get( key ), temp.get( key ) ); ISymbol sym = (ISymbol) symbol.get( key );
if( !checkAmbiguity( sym, temp.get( key ) ) ){
if( data.mode == LookupMode.PREFIX ){
if( data.ambiguities == null ){
data.ambiguities = new HashSet();
}
data.ambiguities.add( sym.getName() );
} else {
throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous );
}
}
} else { } else {
symbol.put( key, temp.get( key ) ); symbol.put( key, temp.get( key ) );
} }
@ -562,7 +605,7 @@ public class ParserSymbolTable {
return symbol; return symbol;
} }
private static void checkAmbiguity( Object obj1, Object obj2 ) throws ParserSymbolTableException{ private static boolean checkAmbiguity( Object obj1, Object obj2 ) throws ParserSymbolTableException{
//it is not ambiguous if they are the same thing and it is static or an enumerator //it is not ambiguous if they are the same thing and it is static or an enumerator
if( obj1 == obj2 ){ if( obj1 == obj2 ){
@ -571,7 +614,7 @@ public class ParserSymbolTable {
while( symbol != null ) { while( symbol != null ) {
TypeInfo type = ((ISymbol)obj1).getTypeInfo(); TypeInfo type = ((ISymbol)obj1).getTypeInfo();
if( !type.checkBit( TypeInfo.isStatic ) && !type.isType( TypeInfo.t_enumerator ) ){ if( !type.checkBit( TypeInfo.isStatic ) && !type.isType( TypeInfo.t_enumerator ) ){
throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous ); return false;
} }
if( iter != null && iter.hasNext() ){ if( iter != null && iter.hasNext() ){
@ -580,9 +623,9 @@ public class ParserSymbolTable {
symbol = null; symbol = null;
} }
} }
return; return true;
} }
throw new ParserSymbolTableException( ParserSymbolTableException.r_Ambiguous ); return false;
} }
/** /**
@ -1160,6 +1203,7 @@ public class ParserSymbolTable {
//if( symbol.getType() == TypeInfo.t_class ){ //if( symbol.getType() == TypeInfo.t_class ){
if( symbol instanceof IDerivableContainerSymbol ){ if( symbol instanceof IDerivableContainerSymbol ){
associated.add( symbol ); associated.add( symbol );
associated.add( symbol.getContainingSymbol() );
getBaseClassesAndContainingNamespaces( (IDerivableContainerSymbol) symbol, associated ); getBaseClassesAndContainingNamespaces( (IDerivableContainerSymbol) symbol, associated );
} }
//if T is a union or enumeration type, its associated namespace is the namespace in //if T is a union or enumeration type, its associated namespace is the namespace in
@ -2188,6 +2232,7 @@ public class ParserSymbolTable {
static protected class LookupData static protected class LookupData
{ {
public Set ambiguities;
public String name; public String name;
public Map usingDirectives; public Map usingDirectives;
public Set visited = new HashSet(); //used to ensure we don't visit things more than once public Set visited = new HashSet(); //used to ensure we don't visit things more than once
@ -2202,6 +2247,7 @@ public class ParserSymbolTable {
public TypeInfo.eType upperType = TypeInfo.t_undef; public TypeInfo.eType upperType = TypeInfo.t_undef;
public boolean qualified = false; public boolean qualified = false;
public boolean ignoreUsingDirectives = false; public boolean ignoreUsingDirectives = false;
public boolean usingDirectivesOnly = false;
public boolean forUserDefinedConversion = false; public boolean forUserDefinedConversion = false;
public Map foundItems = null; public Map foundItems = null;