mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-08-16 04:35:45 +02:00
Patch for Andrew Niefer:
- Modified lookup with respect to resolving ambiguous names, reducing the number of temporary lists/sets. - Modified adding using declarations to properly support overloaded functions. - Added initial support for user defined conversion sequences when resolving overloaded functions.
This commit is contained in:
parent
6b80ff9dd3
commit
09948618e8
4 changed files with 427 additions and 228 deletions
|
@ -1,3 +1,9 @@
|
|||
2003-04-01 Andrew Niefer
|
||||
Parser Symbol Table, modified lookup with respect to resolving ambiguous names,
|
||||
reducing the number of temporary lists/sets. Modified adding using declarations
|
||||
to properly support overloaded functions. Added initial support for user defined
|
||||
conversion sequences when resolving overloaded functions.
|
||||
|
||||
2003-04-01 John Camelon
|
||||
Fixed bug35906
|
||||
Udated Scanner to not puke on certain control characters.
|
||||
|
|
|
@ -72,12 +72,18 @@ public class ParserSymbolTable {
|
|||
|
||||
public Declaration Lookup( String name ) throws ParserSymbolTableException {
|
||||
LookupData data = new LookupData( name, -1 );
|
||||
return Lookup( data, (Declaration) _contextStack.peek() );
|
||||
|
||||
Lookup( data, (Declaration) _contextStack.peek() );
|
||||
|
||||
return ResolveAmbiguities( data );
|
||||
}
|
||||
|
||||
public Declaration ElaboratedLookup( int type, String name ) throws ParserSymbolTableException{
|
||||
LookupData data = new LookupData( name, type );
|
||||
return Lookup( data, (Declaration) _contextStack.peek() );
|
||||
|
||||
Lookup( data, (Declaration) _contextStack.peek() );
|
||||
|
||||
return ResolveAmbiguities( data );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -101,8 +107,12 @@ public class ParserSymbolTable {
|
|||
LookupData data = new LookupData( name, TypeInfo.t_namespace );
|
||||
data.upperType = TypeInfo.t_union;
|
||||
|
||||
foundDeclaration = LookupInContained( data, inDeclaration );
|
||||
|
||||
LookupInContained( data, inDeclaration );
|
||||
|
||||
if( data.foundItems != null ){
|
||||
foundDeclaration = ResolveAmbiguities( data );//, data.foundItems );
|
||||
}
|
||||
|
||||
if( foundDeclaration == null && inDeclaration._containingScope != null ){
|
||||
foundDeclaration = LookupNestedNameSpecifier( name, inDeclaration._containingScope );
|
||||
}
|
||||
|
@ -142,7 +152,9 @@ public class ParserSymbolTable {
|
|||
LookupData data = new LookupData( name, -1 );
|
||||
data.qualified = true;
|
||||
|
||||
return LookupInContained( data, (Declaration) _contextStack.peek() );
|
||||
LookupInContained( data, (Declaration) _contextStack.peek() );
|
||||
|
||||
return ResolveAmbiguities( data );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -155,7 +167,9 @@ public class ParserSymbolTable {
|
|||
public Declaration QualifiedLookup( String name ) throws ParserSymbolTableException{
|
||||
LookupData data = new LookupData( name, -1 );
|
||||
data.qualified = true;
|
||||
return Lookup( data, (Declaration) _contextStack.peek() );
|
||||
Lookup( data, (Declaration) _contextStack.peek() );
|
||||
|
||||
return ResolveAmbiguities( data );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -168,9 +182,13 @@ public class ParserSymbolTable {
|
|||
public Declaration QualifiedFunctionLookup( String name, LinkedList parameters ) throws ParserSymbolTableException{
|
||||
LookupData data = new LookupData( name, TypeInfo.t_function );
|
||||
data.qualified = true;
|
||||
data.parameters = parameters;
|
||||
//if parameters == null, thats no parameters, but we need to distinguish that from
|
||||
//no parameter information at all, so make an empty list.
|
||||
data.parameters = ( parameters == null ) ? new LinkedList() : parameters;
|
||||
|
||||
return Lookup( data, (Declaration) _contextStack.peek() );
|
||||
Lookup( data, (Declaration) _contextStack.peek() );
|
||||
|
||||
return ResolveAmbiguities( data );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -185,9 +203,12 @@ public class ParserSymbolTable {
|
|||
*/
|
||||
public Declaration MemberFunctionLookup( String name, LinkedList parameters ) throws ParserSymbolTableException{
|
||||
LookupData data = new LookupData( name, TypeInfo.t_function );
|
||||
data.parameters = parameters;
|
||||
//if parameters == null, thats no parameters, but we need to distinguish that from
|
||||
//no parameter information at all, so make an empty list.
|
||||
data.parameters = ( parameters == null ) ? new LinkedList() : parameters;
|
||||
|
||||
return Lookup( data, (Declaration) _contextStack.peek() );
|
||||
Lookup( data, (Declaration) _contextStack.peek() );
|
||||
return ResolveAmbiguities( data );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -216,16 +237,19 @@ public class ParserSymbolTable {
|
|||
//figure out the set of associated scopes first, so we can remove those that are searched
|
||||
//during the normal lookup to avoid doing them twice
|
||||
HashSet associated = new HashSet();
|
||||
|
||||
//collect associated namespaces & classes.
|
||||
int size = ( parameters == null ) ? 0 : parameters.size();
|
||||
Iterator iter = ( parameters == null ) ? null : parameters.iterator();
|
||||
|
||||
TypeInfo param = null;
|
||||
Declaration paramType = null;
|
||||
for( int i = size; i > 0; i-- ){
|
||||
param = (TypeInfo) iter.next();
|
||||
paramType = param.getTypeDeclaration();
|
||||
paramType = getFlatTypeInfo( param ).getTypeDeclaration();
|
||||
|
||||
getAssociatedScopes( paramType, associated );
|
||||
|
||||
//if T is a pointer to a data member of class X, its associated namespaces and classes
|
||||
//are those associated with the member type together with those associated with X
|
||||
if( param.getPtrOperator() != null &&
|
||||
|
@ -237,21 +261,22 @@ public class ParserSymbolTable {
|
|||
}
|
||||
|
||||
LookupData data = new LookupData( name, TypeInfo.t_function );
|
||||
data.parameters = parameters;
|
||||
//if parameters == null, thats no parameters, but we need to distinguish that from
|
||||
//no parameter information at all, so make an empty list.
|
||||
data.parameters = ( parameters == null ) ? new LinkedList() : parameters;
|
||||
data.associated = associated;
|
||||
|
||||
Declaration found = Lookup( data, (Declaration) _contextStack.peek() );
|
||||
Lookup( data, (Declaration) _contextStack.peek() );
|
||||
|
||||
Declaration found = ResolveAmbiguities( data );
|
||||
|
||||
//if we haven't found anything, or what we found is not a class member, consider the
|
||||
//associated scopes
|
||||
if( found == null || found._containingScope.getType() != TypeInfo.t_class ){
|
||||
HashSet foundSet = new HashSet();
|
||||
|
||||
if( found != null ){
|
||||
foundSet.add( found );
|
||||
data.foundItems.add( found );
|
||||
}
|
||||
|
||||
|
||||
|
||||
Declaration decl;
|
||||
Declaration temp;
|
||||
|
||||
|
@ -267,14 +292,11 @@ public class ParserSymbolTable {
|
|||
if( associated.contains( decl ) ){
|
||||
data.qualified = true;
|
||||
data.ignoreUsingDirectives = true;
|
||||
temp = Lookup( data, decl );
|
||||
if( temp != null ){
|
||||
foundSet.add( temp );
|
||||
}
|
||||
Lookup( data, decl );
|
||||
}
|
||||
}
|
||||
|
||||
found = ResolveAmbiguities( data, foundSet );
|
||||
found = ResolveAmbiguities( data );
|
||||
}
|
||||
|
||||
return found;
|
||||
|
@ -307,7 +329,9 @@ public class ParserSymbolTable {
|
|||
|
||||
data.stopAt = enclosing;
|
||||
|
||||
return Lookup( data, (Declaration) _contextStack.peek() );
|
||||
Lookup( data, (Declaration) _contextStack.peek() );
|
||||
|
||||
return ResolveAmbiguities( data );
|
||||
}
|
||||
|
||||
public void addUsingDirective( Declaration namespace ) throws ParserSymbolTableException{
|
||||
|
@ -340,38 +364,48 @@ public class ParserSymbolTable {
|
|||
* class being defined, or shall refer to an enumerator for an enumeration
|
||||
* type that is a member of a base class of the class being defined.
|
||||
*/
|
||||
public Declaration addUsingDeclaration( Declaration obj ) throws ParserSymbolTableException{
|
||||
public Declaration addUsingDeclaration( String name ) throws ParserSymbolTableException {
|
||||
return addUsingDeclaration( name, null );
|
||||
}
|
||||
|
||||
public Declaration addUsingDeclaration( String name, Declaration declContext ) throws ParserSymbolTableException{
|
||||
LookupData data = new LookupData( name, -1 );
|
||||
|
||||
if( declContext != null ){
|
||||
push( declContext );
|
||||
data.qualified = true;
|
||||
Lookup( data, (Declaration) _contextStack.peek() );
|
||||
pop();
|
||||
} else {
|
||||
Lookup( data, (Declaration) _contextStack.peek() );
|
||||
}
|
||||
|
||||
//figure out which declaration we are talking about, if it is a set of functions,
|
||||
//then they will be in data.foundItems (since we provided no parameter info);
|
||||
Declaration obj = ResolveAmbiguities( data );
|
||||
|
||||
if( data.foundItems == null ){
|
||||
throw new ParserSymbolTableException();
|
||||
}
|
||||
|
||||
Declaration clone = null;
|
||||
Declaration context = (Declaration) _contextStack.peek();
|
||||
boolean okToAdd = false;
|
||||
|
||||
//7.3.3-4
|
||||
if( context.isType( TypeInfo.t_class, TypeInfo.t_union ) ){
|
||||
//a member of a base class
|
||||
if( obj.getContainingScope().getType() == context.getType() ){
|
||||
okToAdd = ( hasBaseClass( context, obj.getContainingScope() ) > 0 );
|
||||
}
|
||||
//TBD : a member of an _anonymous_ union
|
||||
else if ( obj.getContainingScope().getType() == TypeInfo.t_union ) {
|
||||
Declaration union = obj.getContainingScope();
|
||||
okToAdd = ( hasBaseClass( context, union.getContainingScope() ) > 0 );
|
||||
|
||||
//if obj != null, then that is the only object to consider, so size is 1,
|
||||
//otherwise we consider the foundItems set
|
||||
int size = ( obj == null ) ? data.foundItems.size() : 1;
|
||||
Iterator iter = data.foundItems.iterator();
|
||||
for( int i = size; i > 0; i-- ){
|
||||
obj = ( obj != null && size == 1 ) ? obj : (Declaration) iter.next();
|
||||
|
||||
if( okToAddUsingDeclaration( obj, (Declaration) _contextStack.peek() ) ){
|
||||
clone = (Declaration) obj.clone(); //7.3.3-9
|
||||
addDeclaration( clone );
|
||||
} else {
|
||||
throw new ParserSymbolTableException();
|
||||
}
|
||||
//an enumerator for an enumeration
|
||||
else if ( obj.getType() == TypeInfo.t_enumerator ){
|
||||
Declaration enumeration = obj.getContainingScope();
|
||||
okToAdd = ( hasBaseClass( context, enumeration.getContainingScope() ) > 0 );
|
||||
}
|
||||
} else {
|
||||
okToAdd = true;
|
||||
}
|
||||
|
||||
if( okToAdd ){
|
||||
clone = (Declaration) obj.clone(); //7.3.3-9
|
||||
addDeclaration( clone );
|
||||
} else {
|
||||
throw new ParserSymbolTableException();
|
||||
}
|
||||
return clone;
|
||||
return ( size == 1 ) ? clone : null;
|
||||
}
|
||||
|
||||
public void addDeclaration( Declaration obj ) throws ParserSymbolTableException{
|
||||
|
@ -500,7 +534,10 @@ public class ParserSymbolTable {
|
|||
//check to see if there is already a this object, since using declarations
|
||||
//of function will have them from the original declaration
|
||||
LookupData data = new LookupData( "this", -1 );
|
||||
if( LookupInContained( data, obj ) == null ){
|
||||
LookupInContained( data, obj );
|
||||
//if we didn't find "this" then foundItems will still be null, no need to actually
|
||||
//check its contents
|
||||
if( data.foundItems == null ){
|
||||
Declaration thisObj = new Declaration("this");
|
||||
thisObj.setType( TypeInfo.t_type );
|
||||
thisObj.setTypeDeclaration( obj._containingScope );
|
||||
|
@ -521,24 +558,18 @@ public class ParserSymbolTable {
|
|||
* @return Declaration
|
||||
* @throws ParserSymbolTableException
|
||||
*/
|
||||
static private Declaration Lookup( LookupData data, Declaration inDeclaration ) throws ParserSymbolTableException
|
||||
static private void Lookup( LookupData data, Declaration inDeclaration ) throws ParserSymbolTableException
|
||||
{
|
||||
if( data.type != -1 && data.type < TypeInfo.t_class && data.upperType > TypeInfo.t_union ){
|
||||
throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTypeInfo );
|
||||
}
|
||||
|
||||
Declaration decl = null; //the return value
|
||||
LinkedList tempList = null;
|
||||
LinkedList foundNames = new LinkedList(); //list of names found
|
||||
LinkedList transitives = new LinkedList(); //list of transitive using directives
|
||||
|
||||
|
||||
//if this name define in this scope?
|
||||
decl = LookupInContained( data, inDeclaration );
|
||||
if( decl != null ){
|
||||
foundNames.add( decl );
|
||||
}
|
||||
|
||||
LookupInContained( data, inDeclaration );
|
||||
|
||||
if( !data.ignoreUsingDirectives ){
|
||||
//check nominated namespaces
|
||||
//the transitives list is populated in LookupInNominated, and then
|
||||
|
@ -546,15 +577,11 @@ public class ParserSymbolTable {
|
|||
|
||||
data.visited.clear(); //each namesapce is searched at most once, so keep track
|
||||
|
||||
tempList = LookupInNominated( data, inDeclaration, transitives );
|
||||
|
||||
if( tempList != null ){
|
||||
foundNames.addAll( tempList );
|
||||
}
|
||||
|
||||
LookupInNominated( data, inDeclaration, transitives );
|
||||
|
||||
//if we are doing a qualified lookup, only process using directives if
|
||||
//we haven't found the name yet (and if we aren't ignoring them).
|
||||
if( !data.qualified || foundNames.size() == 0 ){
|
||||
if( !data.qualified || data.foundItems == null ){
|
||||
ProcessDirectives( inDeclaration, data, transitives );
|
||||
|
||||
if( inDeclaration._usingDirectives != null ){
|
||||
|
@ -564,34 +591,36 @@ public class ParserSymbolTable {
|
|||
while( data.usingDirectives != null && data.usingDirectives.get( inDeclaration ) != null ){
|
||||
transitives.clear();
|
||||
|
||||
tempList = LookupInNominated( data, inDeclaration, transitives );
|
||||
|
||||
if( tempList != null ){
|
||||
foundNames.addAll( tempList );
|
||||
}
|
||||
LookupInNominated( data, inDeclaration, transitives );
|
||||
|
||||
if( !data.qualified || foundNames.size() == 0 ){
|
||||
if( !data.qualified || data.foundItems == null ){
|
||||
ProcessDirectives( inDeclaration, data, transitives );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
decl = ResolveAmbiguities( data, new HashSet( foundNames ) );
|
||||
if( decl != null || data.stopAt == inDeclaration ){
|
||||
return decl;
|
||||
if( data.foundItems != null || data.stopAt == inDeclaration ){
|
||||
return;
|
||||
}
|
||||
|
||||
//if we still havn't found it, check any parents we have
|
||||
data.visited.clear(); //each virtual base class is searched at most once
|
||||
decl = LookupInParents( data, inDeclaration );
|
||||
decl = LookupInParents( data, inDeclaration );
|
||||
|
||||
//there is a resolveAmbiguities inside LookupInParents, which means if we found
|
||||
//something the foundItems set will be non-null, but empty. So, add the decl into
|
||||
//the foundItems set
|
||||
if( decl != null ){
|
||||
data.foundItems.add( decl );
|
||||
}
|
||||
|
||||
//if still not found, check our containing scope.
|
||||
if( decl == null && inDeclaration._containingScope != null ){
|
||||
decl = Lookup( data, inDeclaration._containingScope );
|
||||
if( data.foundItems == null && inDeclaration._containingScope != null ){
|
||||
Lookup( data, inDeclaration._containingScope );
|
||||
}
|
||||
|
||||
return decl;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -613,29 +642,28 @@ public class ParserSymbolTable {
|
|||
* directives, the effect is as if the using-directives from the second
|
||||
* namespace also appeared in the first.
|
||||
*/
|
||||
static private LinkedList LookupInNominated( LookupData data, Declaration declaration, LinkedList transitiveDirectives ) throws ParserSymbolTableException{
|
||||
static private void LookupInNominated( LookupData data, Declaration declaration, LinkedList transitiveDirectives ) throws ParserSymbolTableException{
|
||||
//if the data.usingDirectives is empty, there is nothing to do.
|
||||
if( data.usingDirectives == null ){
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
LinkedList found = null; //list of found names to return
|
||||
|
||||
//local variables
|
||||
LinkedList list = null;
|
||||
LinkedList directives = null; //using directives association with declaration
|
||||
Iterator iter = null;
|
||||
Declaration decl = null;
|
||||
Declaration temp = null;
|
||||
|
||||
boolean foundSomething = false;
|
||||
int size = 0;
|
||||
|
||||
list = (LinkedList) data.usingDirectives.remove( declaration );
|
||||
directives = (LinkedList) data.usingDirectives.remove( declaration );
|
||||
|
||||
if( list == null ){
|
||||
return null;
|
||||
if( directives == null ){
|
||||
return;
|
||||
}
|
||||
|
||||
iter = list.iterator();
|
||||
size = list.size();
|
||||
iter = directives.iterator();
|
||||
size = directives.size();
|
||||
for( int i = size; i > 0; i-- ){
|
||||
decl = (Declaration) iter.next();
|
||||
|
||||
|
@ -643,26 +671,18 @@ public class ParserSymbolTable {
|
|||
if( !data.visited.contains( decl ) ){
|
||||
data.visited.add( decl );
|
||||
|
||||
temp = LookupInContained( data, decl );
|
||||
|
||||
//if we found something, add it to the list of found names
|
||||
if( temp != null ){
|
||||
if( found == null ){
|
||||
found = new LinkedList();
|
||||
}
|
||||
found.add( temp );
|
||||
}
|
||||
|
||||
foundSomething = LookupInContained( data, decl );
|
||||
|
||||
//only consider the transitive using directives if we are an unqualified
|
||||
//lookup, or we didn't find the name in decl
|
||||
if( (!data.qualified || temp == null) && decl._usingDirectives != null ){
|
||||
if( (!data.qualified || !foundSomething ) && decl._usingDirectives != null ){
|
||||
//name wasn't found, add transitive using directives for later consideration
|
||||
transitiveDirectives.addAll( decl._usingDirectives );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -673,8 +693,8 @@ public class ParserSymbolTable {
|
|||
*
|
||||
* Look for data.name in our collection _containedDeclarations
|
||||
*/
|
||||
private static Declaration LookupInContained( LookupData data, Declaration lookIn ) throws ParserSymbolTableException{
|
||||
HashSet found = null;
|
||||
private static boolean LookupInContained( LookupData data, Declaration lookIn ) throws ParserSymbolTableException{
|
||||
boolean foundSomething = false;
|
||||
Declaration temp = null;
|
||||
Object obj = null;
|
||||
|
||||
|
@ -685,24 +705,27 @@ public class ParserSymbolTable {
|
|||
|
||||
Map declarations = lookIn.getContainedDeclarations();
|
||||
if( declarations == null )
|
||||
return null;
|
||||
return foundSomething;
|
||||
|
||||
obj = declarations.get( data.name );
|
||||
|
||||
if( obj == null ){
|
||||
//not found
|
||||
return null;
|
||||
return foundSomething;
|
||||
}
|
||||
|
||||
|
||||
//the contained declarations map either to a Declaration object, or to a list
|
||||
//of declaration objects.
|
||||
if( obj.getClass() == Declaration.class ){
|
||||
if( ((Declaration)obj).isType( data.type, data.upperType ) ){
|
||||
return (Declaration) obj;
|
||||
if( data.foundItems == null ){
|
||||
data.foundItems = new HashSet();
|
||||
}
|
||||
data.foundItems.add( obj );
|
||||
foundSomething = true;
|
||||
}
|
||||
} else {
|
||||
found = new HashSet();
|
||||
|
||||
//we have to filter on type so can't just add the list whole to the fount set
|
||||
LinkedList objList = (LinkedList)obj;
|
||||
Iterator iter = objList.iterator();
|
||||
int size = objList.size();
|
||||
|
@ -711,17 +734,16 @@ public class ParserSymbolTable {
|
|||
temp = (Declaration) iter.next();
|
||||
|
||||
if( temp.isType( data.type, data.upperType ) ){
|
||||
found.add(temp);
|
||||
if( data.foundItems == null ){
|
||||
data.foundItems = new HashSet();
|
||||
}
|
||||
data.foundItems.add(temp);
|
||||
foundSomething = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//if none of the found items made it through the type filtering, just
|
||||
//return null instead of an empty list.
|
||||
if( found == null || found.size() == 0 )
|
||||
return null;
|
||||
|
||||
return ResolveAmbiguities( data, found );
|
||||
return foundSomething;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -733,6 +755,7 @@ public class ParserSymbolTable {
|
|||
*/
|
||||
private static Declaration LookupInParents( LookupData data, Declaration lookIn ) throws ParserSymbolTableException{
|
||||
LinkedList scopes = lookIn.getParentScopes();
|
||||
boolean foundSomething = false;
|
||||
Declaration temp = null;
|
||||
Declaration decl = null;
|
||||
|
||||
|
@ -764,8 +787,8 @@ public class ParserSymbolTable {
|
|||
//is circular inheritance
|
||||
if( ! data.inheritanceChain.contains( wrapper.parent ) ){
|
||||
//is this name define in this scope?
|
||||
temp = LookupInContained( data, wrapper.parent );
|
||||
|
||||
LookupInContained( data, wrapper.parent );
|
||||
temp = ResolveAmbiguities( data );
|
||||
if( temp == null ){
|
||||
temp = LookupInParents( data, wrapper.parent );
|
||||
}
|
||||
|
@ -880,85 +903,136 @@ public class ParserSymbolTable {
|
|||
return true;
|
||||
}
|
||||
|
||||
static private Declaration ResolveAmbiguities( LookupData data, HashSet items ) throws ParserSymbolTableException{
|
||||
int size = items.size();
|
||||
Iterator iter = items.iterator();
|
||||
/**
|
||||
*
|
||||
* @param data
|
||||
* @return Declaration
|
||||
* @throws ParserSymbolTableException
|
||||
*
|
||||
* Resolve the foundItems set down to one declaration and return that
|
||||
* declaration.
|
||||
* If we successfully resolve, then the data.foundItems list will be
|
||||
* cleared. If however, we were not able to completely resolve the set,
|
||||
* then the data.foundItems set will be left with those items that
|
||||
* survived the partial resolution and we will return null. (currently,
|
||||
* this case applies to when we have overloaded functions and no parameter
|
||||
* information)
|
||||
*
|
||||
* NOTE: data.parameters == null means there is no parameter information at
|
||||
* all, when looking for functions with no parameters, an empty list must be
|
||||
* provided in data.parameters.
|
||||
*/
|
||||
static private Declaration ResolveAmbiguities( LookupData data ) throws ParserSymbolTableException{
|
||||
Declaration decl = null;
|
||||
Declaration obj = null;
|
||||
Declaration cls = null;
|
||||
|
||||
if( data.foundItems == null ){
|
||||
return null;
|
||||
}
|
||||
|
||||
int size = data.foundItems.size();
|
||||
Iterator iter = data.foundItems.iterator();
|
||||
|
||||
boolean needDecl = true;
|
||||
|
||||
if( size == 0){
|
||||
return null;
|
||||
} else if (size == 1) {
|
||||
return (Declaration) iter.next();
|
||||
} else {
|
||||
LinkedList functionList = null;
|
||||
|
||||
Declaration decl = null;
|
||||
Declaration obj = null;
|
||||
Declaration cls = null;
|
||||
|
||||
for( int i = size; i > 0; i-- ){
|
||||
decl = (Declaration) iter.next();
|
||||
|
||||
if( decl.isType( TypeInfo.t_function ) ){
|
||||
if( functionList == null){
|
||||
functionList = new LinkedList();
|
||||
}
|
||||
functionList.add( decl );
|
||||
} else {
|
||||
//if this is a class-name, other stuff hides it
|
||||
if( decl.isType( TypeInfo.t_class, TypeInfo.t_enumeration ) ){
|
||||
if( cls == null ) {
|
||||
cls = decl;
|
||||
} else {
|
||||
throw new ParserSymbolTableException( ParserSymbolTableException.r_AmbiguousName );
|
||||
}
|
||||
} else {
|
||||
//an object, can only have one of these
|
||||
if( obj == null ){
|
||||
obj = decl;
|
||||
} else {
|
||||
throw new ParserSymbolTableException( ParserSymbolTableException.r_AmbiguousName );
|
||||
}
|
||||
}
|
||||
}
|
||||
decl = (Declaration) iter.next();
|
||||
//if it is a function we need to check its parameters
|
||||
if( !decl.isType( TypeInfo.t_function ) ){
|
||||
data.foundItems.clear();
|
||||
return decl;
|
||||
}
|
||||
needDecl = false;
|
||||
}
|
||||
|
||||
int numFunctions = ( functionList == null ) ? 0 : functionList.size();
|
||||
LinkedList functionList = null;
|
||||
|
||||
for( int i = size; i > 0; i-- ){
|
||||
//if we
|
||||
if( needDecl ){
|
||||
decl = (Declaration) iter.next();
|
||||
} else {
|
||||
needDecl = true;
|
||||
}
|
||||
|
||||
boolean ambiguous = false;
|
||||
|
||||
if( cls != null ){
|
||||
//the class is only hidden by other stuff if they are from the same scope
|
||||
if( obj != null && cls._containingScope != obj._containingScope ){
|
||||
ambiguous = true;
|
||||
if( decl.isType( TypeInfo.t_function ) ){
|
||||
if( functionList == null){
|
||||
functionList = new LinkedList();
|
||||
}
|
||||
if( functionList != null ){
|
||||
Iterator fnIter = functionList.iterator();
|
||||
Declaration fn = null;
|
||||
for( int i = numFunctions; i > 0; i-- ){
|
||||
fn = (Declaration) fnIter.next();
|
||||
if( cls._containingScope != fn._containingScope ){
|
||||
ambiguous = true;
|
||||
break;
|
||||
}
|
||||
functionList.add( decl );
|
||||
} else {
|
||||
//if this is a class-name, other stuff hides it
|
||||
if( decl.isType( TypeInfo.t_class, TypeInfo.t_enumeration ) ){
|
||||
if( cls == null ) {
|
||||
cls = decl;
|
||||
} else {
|
||||
throw new ParserSymbolTableException( ParserSymbolTableException.r_AmbiguousName );
|
||||
}
|
||||
} else {
|
||||
//an object, can only have one of these
|
||||
if( obj == null ){
|
||||
obj = decl;
|
||||
} else {
|
||||
throw new ParserSymbolTableException( ParserSymbolTableException.r_AmbiguousName );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( obj != null && !ambiguous ){
|
||||
if( numFunctions > 0 ){
|
||||
ambiguous = true;
|
||||
} else {
|
||||
return obj;
|
||||
decl = null;
|
||||
}
|
||||
|
||||
data.foundItems.clear();
|
||||
|
||||
int numFunctions = ( functionList == null ) ? 0 : functionList.size();
|
||||
|
||||
boolean ambiguous = false;
|
||||
|
||||
if( cls != null ){
|
||||
//the class is only hidden by other stuff if they are from the same scope
|
||||
if( obj != null && cls._containingScope != obj._containingScope ){
|
||||
ambiguous = true;
|
||||
}
|
||||
if( functionList != null ){
|
||||
Iterator fnIter = functionList.iterator();
|
||||
Declaration fn = null;
|
||||
for( int i = numFunctions; i > 0; i-- ){
|
||||
fn = (Declaration) fnIter.next();
|
||||
if( cls._containingScope != fn._containingScope ){
|
||||
ambiguous = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if( numFunctions > 0 ) {
|
||||
}
|
||||
}
|
||||
|
||||
if( obj != null && !ambiguous ){
|
||||
if( numFunctions > 0 ){
|
||||
ambiguous = true;
|
||||
} else {
|
||||
return obj;
|
||||
}
|
||||
} else if( numFunctions > 0 ) {
|
||||
if( data.parameters == null ){
|
||||
//we have no parameter information, if we only have one function, return
|
||||
//that, otherwise we can't decide between them
|
||||
if( numFunctions == 1){
|
||||
return (Declaration) functionList.getFirst();
|
||||
} else {
|
||||
data.foundItems.addAll( functionList );
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return ResolveFunction( data, functionList );
|
||||
}
|
||||
|
||||
if( ambiguous ){
|
||||
throw new ParserSymbolTableException( ParserSymbolTableException.r_AmbiguousName );
|
||||
} else {
|
||||
return cls;
|
||||
}
|
||||
}
|
||||
|
||||
if( ambiguous ){
|
||||
throw new ParserSymbolTableException( ParserSymbolTableException.r_AmbiguousName );
|
||||
} else {
|
||||
return cls;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1023,15 +1097,10 @@ public class ParserSymbolTable {
|
|||
if( source.equals( target ) ){
|
||||
cost = 0; //exact match, no cost
|
||||
} else {
|
||||
if( !canDoQualificationConversion( source, target ) ){
|
||||
//matching qualification is at no cost, but not matching is a failure
|
||||
cost = -1;
|
||||
} else if( (temp = canPromote( source, target )) >= 0 ){
|
||||
cost = temp;
|
||||
} else if( (temp = canConvert( source, target )) >= 0 ){
|
||||
cost = temp; //cost for conversion has to do with "distance" between source and target
|
||||
} else {
|
||||
cost = -1; //failure
|
||||
cost = checkStandardConversionSequence( source, target );
|
||||
|
||||
if( cost == -1){
|
||||
cost = checkUserDefinedConversionSequence( source, target );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1269,6 +1338,32 @@ public class ParserSymbolTable {
|
|||
}
|
||||
}
|
||||
|
||||
static private boolean okToAddUsingDeclaration( Declaration obj, Declaration context ){
|
||||
boolean okToAdd = false;
|
||||
|
||||
//7.3.3-4
|
||||
if( context.isType( TypeInfo.t_class, TypeInfo.t_union ) ){
|
||||
//a member of a base class
|
||||
if( obj.getContainingScope().getType() == context.getType() ){
|
||||
okToAdd = ( hasBaseClass( context, obj.getContainingScope() ) > 0 );
|
||||
}
|
||||
//TBD : a member of an _anonymous_ union
|
||||
else if ( obj.getContainingScope().getType() == TypeInfo.t_union ) {
|
||||
Declaration union = obj.getContainingScope();
|
||||
okToAdd = ( hasBaseClass( context, union.getContainingScope() ) > 0 );
|
||||
}
|
||||
//an enumerator for an enumeration
|
||||
else if ( obj.getType() == TypeInfo.t_enumerator ){
|
||||
Declaration enumeration = obj.getContainingScope();
|
||||
okToAdd = ( hasBaseClass( context, enumeration.getContainingScope() ) > 0 );
|
||||
}
|
||||
} else {
|
||||
okToAdd = true;
|
||||
}
|
||||
|
||||
return okToAdd;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param source
|
||||
|
@ -1391,6 +1486,50 @@ public class ParserSymbolTable {
|
|||
return -1;
|
||||
}
|
||||
|
||||
static private int checkStandardConversionSequence( TypeInfo source, TypeInfo target ) throws ParserSymbolTableException {
|
||||
int cost = -1;
|
||||
int temp = 0;
|
||||
|
||||
if( !canDoQualificationConversion( source, target ) ){
|
||||
//matching qualification is at no cost, but not matching is a failure
|
||||
cost = -1;
|
||||
} else if( (temp = canPromote( source, target )) >= 0 ){
|
||||
cost = temp;
|
||||
} else if( (temp = canConvert( source, target )) >= 0 ){
|
||||
cost = temp; //cost for conversion has to do with "distance" between source and target
|
||||
} else {
|
||||
cost = -1; //failure
|
||||
}
|
||||
|
||||
return cost;
|
||||
}
|
||||
|
||||
static private int checkUserDefinedConversionSequence( TypeInfo source, TypeInfo target ) throws ParserSymbolTableException {
|
||||
int cost = -1;
|
||||
Declaration targetDecl = null;
|
||||
Declaration constructor = null;
|
||||
|
||||
if( target.getType() == TypeInfo.t_type ){
|
||||
targetDecl = target.getTypeDeclaration();
|
||||
if( targetDecl.isType( TypeInfo.t_class, TypeInfo.t_union ) ){
|
||||
LookupData data = new LookupData( "", TypeInfo.t_function );
|
||||
LinkedList params = new LinkedList();
|
||||
params.add( source );
|
||||
data.parameters = params;
|
||||
LookupInContained( data, targetDecl );
|
||||
constructor = ResolveAmbiguities( data );
|
||||
if( constructor != null ){
|
||||
cost = checkStandardConversionSequence( new TypeInfo( TypeInfo.t_type, constructor._containingScope ), target );
|
||||
if( cost != -1 ){
|
||||
cost++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
static private boolean canDoQualificationConversion( TypeInfo source, TypeInfo target ){
|
||||
return ( source.getCVQualifier() == source.getCVQualifier() ||
|
||||
(source.getCVQualifier() - source.getCVQualifier()) > 1 );
|
||||
|
@ -1411,7 +1550,7 @@ public class ParserSymbolTable {
|
|||
if( topInfo.getType() == TypeInfo.t_type ){
|
||||
returnInfo = new TypeInfo();
|
||||
|
||||
Declaration typeDecl = null;
|
||||
Declaration typeDecl = topInfo.getTypeDeclaration();
|
||||
|
||||
info = topInfo.getTypeDeclaration().getTypeInfo();
|
||||
|
||||
|
@ -1441,7 +1580,7 @@ public class ParserSymbolTable {
|
|||
private Stack _contextStack = new Stack();
|
||||
private Declaration _compilationUnit;
|
||||
|
||||
private class LookupData
|
||||
static private class LookupData
|
||||
{
|
||||
|
||||
public String name;
|
||||
|
@ -1459,6 +1598,8 @@ public class ParserSymbolTable {
|
|||
public boolean qualified = false;
|
||||
public boolean ignoreUsingDirectives = false;
|
||||
|
||||
public HashSet foundItems = null;
|
||||
|
||||
public LookupData( String n, int t ){
|
||||
name = n;
|
||||
type = t;
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2003-04-01 Andrew Niefer
|
||||
ParserSymbolTableTest. modifications to using declaration tests to reflect changes in the
|
||||
symbol table. Also added testUserDefinedConversionSequences()
|
||||
|
||||
2003-04-01
|
||||
Added testBug35906() to DOMTests.
|
||||
|
||||
|
|
|
@ -1146,34 +1146,19 @@ public class ParserSymbolTableTest extends TestCase {
|
|||
|
||||
Declaration lookB = table.LookupNestedNameSpecifier("B");
|
||||
assertEquals( lookB, B );
|
||||
table.push( lookB );
|
||||
look = table.QualifiedLookup( "f" );
|
||||
table.pop();
|
||||
|
||||
table.addUsingDeclaration( "f", lookB );
|
||||
|
||||
assertEquals( look, f );
|
||||
table.addUsingDeclaration( look );
|
||||
|
||||
table.push( lookB );
|
||||
look = table.QualifiedLookup( "e" );
|
||||
table.pop();
|
||||
assertEquals( look, e );
|
||||
table.addUsingDeclaration( look );
|
||||
table.addUsingDeclaration( "e", lookB );
|
||||
|
||||
//TBD anonymous union
|
||||
//table.push( lookB );
|
||||
//look = table.QualifiedLookup( "x")
|
||||
//table.pop();
|
||||
//table.addUsingDeclaration( look );
|
||||
//table.addUsingDeclaration( "x", lookB );
|
||||
|
||||
look = table.LookupNestedNameSpecifier("C");
|
||||
assertEquals( look, C );
|
||||
table.push( look );
|
||||
look = table.QualifiedLookup("g");
|
||||
table.pop();
|
||||
assertEquals( look, g );
|
||||
|
||||
try{
|
||||
table.addUsingDeclaration( look );
|
||||
table.addUsingDeclaration( "g", look );
|
||||
assertTrue( false );
|
||||
}
|
||||
catch ( ParserSymbolTableException exception ){
|
||||
|
@ -1204,10 +1189,6 @@ public class ParserSymbolTableTest extends TestCase {
|
|||
* using A::f;
|
||||
* f('a'); //calls f( char );
|
||||
* }
|
||||
*
|
||||
* TBD: we need to support using declarations for overloaded functions.
|
||||
* TBD: function overload resolution is not done yet, so the call to f in
|
||||
* bar() can't be tested yet.
|
||||
*/
|
||||
public void testUsingDeclaration_2() throws Exception{
|
||||
newTable();
|
||||
|
@ -1228,12 +1209,8 @@ public class ParserSymbolTableTest extends TestCase {
|
|||
|
||||
Declaration look = table.LookupNestedNameSpecifier("A");
|
||||
assertEquals( look, A );
|
||||
table.push( A );
|
||||
look = table.QualifiedLookup("f");
|
||||
assertEquals( look, f1 );
|
||||
table.pop();
|
||||
|
||||
Declaration usingF = table.addUsingDeclaration( look );
|
||||
Declaration usingF = table.addUsingDeclaration( "f", look );
|
||||
|
||||
look = table.Lookup("A");
|
||||
assertEquals( look, A );
|
||||
|
@ -1258,7 +1235,23 @@ public class ParserSymbolTableTest extends TestCase {
|
|||
|
||||
look = table.UnqualifiedFunctionLookup( "f", paramList );
|
||||
assertEquals( look, usingF );
|
||||
assertTrue( look.hasSameParameters( f1 ) );
|
||||
|
||||
Declaration bar = new Declaration( "bar" );
|
||||
bar.setType( TypeInfo.t_function );
|
||||
bar.addParameter( TypeInfo.t_char, 0, null, false );
|
||||
table.addDeclaration( bar );
|
||||
table.push( bar );
|
||||
|
||||
look = table.LookupNestedNameSpecifier( "A" );
|
||||
assertEquals( look, A );
|
||||
table.addUsingDeclaration( "f", A );
|
||||
|
||||
look = table.UnqualifiedFunctionLookup( "f", paramList );
|
||||
assertTrue( look != null );
|
||||
assertTrue( look.hasSameParameters( f2 ) );
|
||||
|
||||
table.pop();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1389,8 +1382,8 @@ public class ParserSymbolTableTest extends TestCase {
|
|||
LinkedList paramList = new LinkedList();
|
||||
look = table.Lookup( "parm" );
|
||||
assertEquals( look, param );
|
||||
|
||||
paramList.add( look.getTypeInfo() );
|
||||
TypeInfo p = new TypeInfo( TypeInfo.t_type, look, 0, null, false );
|
||||
paramList.add( p );
|
||||
|
||||
look = table.UnqualifiedFunctionLookup( "f", paramList );
|
||||
assertEquals( look, f );
|
||||
|
@ -1765,5 +1758,60 @@ public class ParserSymbolTableTest extends TestCase {
|
|||
assertEquals( look, f1 );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @throws Exception
|
||||
*
|
||||
* class A {};
|
||||
*
|
||||
* class B
|
||||
* {
|
||||
* B( A a ){ };
|
||||
* };
|
||||
*
|
||||
* void f( B b ){};
|
||||
*
|
||||
* A a;
|
||||
* f( a );
|
||||
*/
|
||||
public void testUserDefinedConversionSequences() throws Exception{
|
||||
newTable();
|
||||
|
||||
Declaration A = new Declaration( "A" );
|
||||
A.setType( TypeInfo.t_class );
|
||||
table.addDeclaration( A );
|
||||
|
||||
Declaration B = new Declaration( "B" );
|
||||
B.setType( TypeInfo.t_class );
|
||||
table.addDeclaration( B );
|
||||
|
||||
table.push( B );
|
||||
|
||||
//12.1-1 "Constructors do not have names"
|
||||
Declaration constructor = new Declaration("");
|
||||
constructor.setType( TypeInfo.t_function );
|
||||
constructor.addParameter( A, 0, null, false );
|
||||
table.addDeclaration( constructor );
|
||||
|
||||
table.pop();
|
||||
|
||||
Declaration f = new Declaration( "f" );
|
||||
f.setType( TypeInfo.t_function );
|
||||
f.addParameter( B, 0, null, false );
|
||||
table.addDeclaration( f );
|
||||
|
||||
Declaration a = new Declaration( "a" );
|
||||
a.setType( TypeInfo.t_type );
|
||||
a.setTypeDeclaration( A );
|
||||
table.addDeclaration( a );
|
||||
|
||||
LinkedList paramList = new LinkedList();
|
||||
TypeInfo p = new TypeInfo( TypeInfo.t_type, a, 0, null, false );
|
||||
paramList.add( p );
|
||||
|
||||
Declaration look = table.UnqualifiedFunctionLookup( "f", paramList );
|
||||
assertEquals( look, f );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue