1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-06-08 18:26:01 +02:00

Patch for Andrew Niefer:

- This patch contains my initial implementation of standard conversion 
sequences for function resolution in the Parser's symbol Table. 
- Also, the type information has been pulled out of the Declaration object and 
placed in util.TypeInfo
This commit is contained in:
Doug Schaefer 2003-03-27 03:29:08 +00:00
parent d24ccf7f26
commit f77eeb8c08
6 changed files with 835 additions and 400 deletions

View file

@ -1,3 +1,7 @@
2003-03-26 Andrew Niefer
Moved type information and ParameterInfo from Declaration into util.TypeInfo
Initial implementation of standard conversion sequences for function resolution
2003-03-24 John Camelon
Added callback support for namespace definitions.
Updated Parser exception hierarchy.

View file

@ -16,6 +16,8 @@ import java.util.LinkedList;
import java.util.Map;
import java.util.Iterator;
import org.eclipse.cdt.internal.core.parser.util.TypeInfo;
/**
* @author aniefer
*
@ -32,15 +34,20 @@ public class Declaration implements Cloneable {
*/
public Declaration(){
super();
_typeInfo = new TypeInfo();
}
public Declaration( String name ){
super();
_name = name;
_typeInfo = new TypeInfo();
}
public Declaration( String name, Object obj ){
super();
_name = name;
_object = obj;
_typeInfo = new TypeInfo();
}
/**
@ -77,134 +84,32 @@ public class Declaration implements Cloneable {
return copy;
}
public static final int typeMask = 0x001f;
public static final int isAuto = 0x0020;
public static final int isRegister = 0x0040;
public static final int isStatic = 0x0080;
public static final int isExtern = 0x0100;
public static final int isMutable = 0x0200;
public static final int isInline = 0x0400;
public static final int isVirtual = 0x0800;
public static final int isExplicit = 0x1000;
public static final int isTypedef = 0x2000;
public static final int isFriend = 0x4000;
public static final int isConst = 0x8000;
public static final int isVolatile = 0x10000;
public static final int isUnsigned = 0x20000;
public static final int isShort = 0x40000;
public static final int isLong = 0x80000;
public void setAuto(boolean b) { setBit(b, isAuto); }
public boolean isAuto() { return checkBit(isAuto); }
public void setRegister(boolean b) { setBit(b, isRegister); }
public boolean isRegister() { return checkBit(isRegister); }
public void setStatic(boolean b) { setBit(b, isStatic); }
public boolean isStatic() { return checkBit(isStatic); }
public void setExtern(boolean b) { setBit(b, isExtern); }
public boolean isExtern() { return checkBit(isExtern); }
public void setMutable(boolean b) { setBit(b, isMutable); }
public boolean isMutable() { return checkBit(isMutable); }
public void setInline(boolean b) { setBit(b, isInline); }
public boolean isInline() { return checkBit(isInline); }
public void setVirtual(boolean b) { setBit(b, isVirtual); }
public boolean isVirtual() { return checkBit(isVirtual); }
public void setExplicit(boolean b) { setBit(b, isExplicit); }
public boolean isExplicit() { return checkBit(isExplicit); }
public void setTypedef(boolean b) { setBit(b, isTypedef); }
public boolean isTypedef() { return checkBit(isTypedef); }
public void setFriend(boolean b) { setBit(b, isFriend); }
public boolean isFriend() { return checkBit(isFriend); }
public void setConst(boolean b) { setBit(b, isConst); }
public boolean isConst() { return checkBit(isConst); }
public void setVolatile(boolean b) { setBit(b, isVolatile); }
public boolean isVolatile() { return checkBit(isVolatile); }
public void setUnsigned(boolean b) { setBit(b, isUnsigned); }
public boolean isUnsigned() { return checkBit(isUnsigned); }
public void setShort(boolean b) { setBit(b, isShort); }
public boolean isShort() { return checkBit(isShort); }
public void setLong(boolean b) { setBit(b, isLong); }
public boolean isLong() { return checkBit(isLong); }
// Types
// Note that these should be considered ordered and if you change
// the order, you should consider the ParserSymbolTable uses
public static final int t_type = 0; // Type Specifier
public static final int t_namespace = 1;
public static final int t_class = 2;
public static final int t_struct = 3;
public static final int t_union = 4;
public static final int t_enumeration = 5;
public static final int t_function = 6;
public static final int t_char = 7;
public static final int t_wchar_t = 8;
public static final int t_bool = 9;
public static final int t_int = 10;
public static final int t_float = 11;
public static final int t_double = 12;
public static final int t_void = 13;
public static final int t_enumerator = 14;
public void setType(int t) throws ParserSymbolTableException{
//sanity check, t must fit in its allocated 5 bits in _typeInfo
if( t > typeMask ){
throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTypeInfo );
}
_typeInfo = _typeInfo & ~typeMask | t;
public void setType(int t) throws ParserSymbolTableException{
_typeInfo.setType( t );
}
public int getType(){
return _typeInfo & typeMask;
return _typeInfo.getType();
}
public boolean isType( int type ){
return isType( type, 0 );
return _typeInfo.isType( type, 0 );
}
/**
*
* @param type
* @param upperType
* @return boolean
*
* type checking, check that this declaration's type is between type and
* upperType (inclusive). upperType of 0 means no range and our type must
* be type.
*/
public boolean isType( int type, int upperType ){
//type of -1 means we don't care
if( type == -1 )
return true;
//upperType of 0 means no range
if( upperType == 0 ){
return ( getType() == type );
} else {
return ( getType() >= type && getType() <= upperType );
}
return _typeInfo.isType( type, upperType );
}
public Declaration getTypeDeclaration(){
return _typeDeclaration;
return _typeInfo.getTypeDeclaration();
}
public void setTypeDeclaration( Declaration type ){
_typeDeclaration = type;
_typeInfo.setTypeDeclaration( type );
}
public TypeInfo getTypeInfo(){
return _typeInfo;
}
public String getName() { return _name; }
@ -252,11 +157,11 @@ public class Declaration implements Cloneable {
_needsDefinition = need;
}
public String getCVQualifier(){
public int getCVQualifier(){
return _cvQualifier;
}
public void setCVQualifier( String cv ){
public void setCVQualifier( int cv ){
_cvQualifier = cv;
}
@ -275,30 +180,22 @@ public class Declaration implements Cloneable {
_returnType = type;
}
public void addParameter( Declaration typeDecl, String ptrOperator, boolean hasDefault ){
public void addParameter( Declaration typeDecl, int cvQual, String ptrOperator, boolean hasDefault ){
if( _parameters == null ){
_parameters = new LinkedList();
}
ParameterInfo info = new ParameterInfo();
info.typeInfo = t_type;
info.typeDeclaration = typeDecl;
info.ptrOperator = ptrOperator;
info.hasDefaultValue = hasDefault;
TypeInfo info = new TypeInfo( TypeInfo.t_type, typeDecl, cvQual, ptrOperator, hasDefault );
_parameters.add( info );
}
public void addParameter( int type, String ptrOperator, boolean hasDefault ){
public void addParameter( int type, int cvQual, String ptrOperator, boolean hasDefault ){
if( _parameters == null ){
_parameters = new LinkedList();
}
ParameterInfo info = new ParameterInfo();
info.typeInfo = type;
info.typeDeclaration = null;
info.ptrOperator = ptrOperator;
info.hasDefaultValue = hasDefault;
TypeInfo info = new TypeInfo(type, null, cvQual, ptrOperator, hasDefault );
_parameters.add( info );
}
@ -316,12 +213,12 @@ public class Declaration implements Cloneable {
Iterator iter = _parameters.iterator();
Iterator fIter = function._parameters.iterator();
ParameterInfo info = null;
ParameterInfo fInfo = null;
TypeInfo info = null;
TypeInfo fInfo = null;
for( int i = size; i > 0; i-- ){
info = (ParameterInfo) iter.next();
fInfo = (ParameterInfo) fIter.next();
info = (TypeInfo) iter.next();
fInfo = (TypeInfo) fIter.next();
if( !info.equals( fInfo ) ){
return false;
@ -332,26 +229,12 @@ public class Declaration implements Cloneable {
return true;
}
// Convenience methods
private void setBit(boolean b, int mask){
if( b ){
_typeInfo = _typeInfo | mask;
} else {
_typeInfo = _typeInfo & ~mask;
}
}
private boolean checkBit(int mask){
return (_typeInfo & mask) != 0;
}
private int _typeInfo; //our type info
private String _name; //our name
private Object _object; //the object associated with us
private Declaration _typeDeclaration; //our type if _typeInfo says t_type
private boolean _needsDefinition; //this name still needs to be defined
private String _cvQualifier;
private int _cvQualifier;
private String _ptrOperator;
protected TypeInfo _typeInfo; //our type info
protected Declaration _containingScope; //the scope that contains us
protected LinkedList _parentScopes; //inherited scopes (is base classes)
protected LinkedList _usingDirectives; //collection of nominated namespaces
@ -372,27 +255,4 @@ public class Declaration implements Cloneable {
public boolean isVirtual = false;
public Declaration parent = null;
}
public class ParameterInfo
{
public ParameterInfo() {}
public ParameterInfo( int t, Declaration decl, String ptr, boolean def ){
typeInfo = t;
typeDeclaration = decl;
ptrOperator = ptr;
hasDefaultValue = def;
}
public boolean equals( ParameterInfo obj ){
return ( hasDefaultValue == obj.hasDefaultValue ) &&
( typeInfo == obj.typeInfo ) &&
( typeDeclaration == obj.typeDeclaration ) &&
( ptrOperator.equals( obj.ptrOperator ) );
}
public boolean hasDefaultValue;
public int typeInfo;
public Declaration typeDeclaration;
public String ptrOperator;
}
}

View file

@ -22,6 +22,8 @@ import java.util.Map;
import java.util.Set;
import java.util.Stack;
import org.eclipse.cdt.internal.core.parser.util.TypeInfo;
/**
* @author aniefer
*
@ -40,7 +42,7 @@ public class ParserSymbolTable {
super();
_compilationUnit = new Declaration();
try{
_compilationUnit.setType( Declaration.t_namespace );
_compilationUnit.setType( TypeInfo.t_namespace );
} catch ( ParserSymbolTableException e ){
/*shouldn't happen*/
}
@ -96,8 +98,8 @@ public class ParserSymbolTable {
private Declaration LookupNestedNameSpecifier(String name, Declaration inDeclaration ) throws ParserSymbolTableException{
Declaration foundDeclaration = null;
LookupData data = new LookupData( name, Declaration.t_namespace );
data.upperType = Declaration.t_union;
LookupData data = new LookupData( name, TypeInfo.t_namespace );
data.upperType = TypeInfo.t_union;
foundDeclaration = LookupInContained( data, inDeclaration );
@ -164,7 +166,7 @@ public class ParserSymbolTable {
* @throws ParserSymbolTableException
*/
public Declaration QualifiedFunctionLookup( String name, LinkedList parameters ) throws ParserSymbolTableException{
LookupData data = new LookupData( name, Declaration.t_function );
LookupData data = new LookupData( name, TypeInfo.t_function );
data.qualified = true;
data.parameters = parameters;
@ -182,7 +184,7 @@ public class ParserSymbolTable {
* include argument dependant scopes
*/
public Declaration MemberFunctionLookup( String name, LinkedList parameters ) throws ParserSymbolTableException{
LookupData data = new LookupData( name, Declaration.t_function );
LookupData data = new LookupData( name, TypeInfo.t_function );
data.parameters = parameters;
return Lookup( data, (Declaration) _contextStack.peek() );
@ -215,24 +217,26 @@ public class ParserSymbolTable {
//during the normal lookup to avoid doing them twice
HashSet associated = new HashSet();
//collect associated namespaces & classes.
int size = parameters.size();
Iterator iter = parameters.iterator();
Declaration.ParameterInfo param = null;
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 = (Declaration.ParameterInfo) iter.next();
param = (TypeInfo) iter.next();
paramType = param.getTypeDeclaration();
getAssociatedScopes( param.typeDeclaration, associated );
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.ptrOperator != null &&
(param.ptrOperator.equals("*") || param.ptrOperator.equals("[]")) &&
param.typeDeclaration._containingScope.isType( Declaration.t_class, Declaration.t_union ) )
if( param.getPtrOperator() != null &&
(param.getPtrOperator().equals("*") || param.getPtrOperator().equals("[]")) &&
paramType._containingScope.isType( TypeInfo.t_class, TypeInfo.t_union ) )
{
getAssociatedScopes( param.typeDeclaration._containingScope, associated );
getAssociatedScopes( paramType._containingScope, associated );
}
}
LookupData data = new LookupData( name, Declaration.t_function );
LookupData data = new LookupData( name, TypeInfo.t_function );
data.parameters = parameters;
data.associated = associated;
@ -240,33 +244,37 @@ public class ParserSymbolTable {
//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() != Declaration.t_class ){
LinkedList foundList = new LinkedList();
if( found == null || found._containingScope.getType() != TypeInfo.t_class ){
HashSet foundSet = new HashSet();
if( found != null ){
foundList.add( found );
foundSet.add( found );
}
iter = associated.iterator();
Declaration decl;
Declaration temp;
//dump the hash to an array and iterate over the array because we
//could be removing items from the collection as we go and we don't
//want to get ConcurrentModificationExceptions
Object [] scopes = associated.toArray();
//use while hasNext instead of forloop since the lookup might remove
//items from the collection.
//Actually, I think that there will be no removals, but leave it like this anyway
while( iter.hasNext() ){
decl = (Declaration) iter.next();
data.qualified = true;
data.ignoreUsingDirectives = true;
temp = Lookup( data, decl );
if( temp != null ){
foundList.add( temp );
size = associated.size();
for( int i = 0; i < size; i++ ){
decl = (Declaration) scopes[ i ];
if( associated.contains( decl ) ){
data.qualified = true;
data.ignoreUsingDirectives = true;
temp = Lookup( data, decl );
if( temp != null ){
foundSet.add( temp );
}
}
}
found = ResolveAmbiguities( data, foundList );
found = ResolveAmbiguities( data, foundSet );
}
return found;
@ -288,11 +296,11 @@ public class ParserSymbolTable {
LookupData data = new LookupData( name, -1 );
Declaration decl = (Declaration) _contextStack.peek();
boolean inClass = (decl.getType() == Declaration.t_class);
boolean inClass = (decl.getType() == TypeInfo.t_class);
Declaration enclosing = decl._containingScope;
while( enclosing != null && (inClass ? enclosing.getType() != Declaration.t_class
: enclosing.getType() == Declaration.t_namespace) )
while( enclosing != null && (inClass ? enclosing.getType() != TypeInfo.t_class
: enclosing.getType() == TypeInfo.t_namespace) )
{
enclosing = enclosing._containingScope;
}
@ -303,7 +311,7 @@ public class ParserSymbolTable {
}
public void addUsingDirective( Declaration namespace ) throws ParserSymbolTableException{
if( namespace.getType() != Declaration.t_namespace ){
if( namespace.getType() != TypeInfo.t_namespace ){
throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTypeInfo );
}
@ -338,20 +346,20 @@ public class ParserSymbolTable {
boolean okToAdd = false;
//7.3.3-4
if( context.isType( Declaration.t_class, Declaration.t_union ) ){
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() );
okToAdd = ( hasBaseClass( context, obj.getContainingScope() ) > 0 );
}
//TBD : a member of an _anonymous_ union
else if ( obj.getContainingScope().getType() == Declaration.t_union ) {
else if ( obj.getContainingScope().getType() == TypeInfo.t_union ) {
Declaration union = obj.getContainingScope();
okToAdd = hasBaseClass( context, union.getContainingScope() );
okToAdd = ( hasBaseClass( context, union.getContainingScope() ) > 0 );
}
//an enumerator for an enumeration
else if ( obj.getType() == Declaration.t_enumerator ){
else if ( obj.getType() == TypeInfo.t_enumerator ){
Declaration enumeration = obj.getContainingScope();
okToAdd = hasBaseClass( context, enumeration.getContainingScope() );
okToAdd = ( hasBaseClass( context, enumeration.getContainingScope() ) > 0 );
}
} else {
okToAdd = true;
@ -371,10 +379,10 @@ public class ParserSymbolTable {
Declaration containing = (Declaration) _contextStack.peek();
//handle enumerators
if( obj.getType() == Declaration.t_enumerator ){
if( obj.getType() == TypeInfo.t_enumerator ){
//a using declaration of an enumerator will not be contained in a
//enumeration.
if( containing.getType() == Declaration.t_enumeration ){
if( containing.getType() == TypeInfo.t_enumeration ){
//Following the closing brace of an enum-specifier, each enumerator has the type of its
//enumeration
obj.setTypeDeclaration( containing );
@ -431,7 +439,8 @@ public class ParserSymbolTable {
}
//take care of the this pointer
if( obj.getType() == Declaration.t_function && !obj.isStatic() ){
TypeInfo type = obj._typeInfo;
if( type.isType( TypeInfo.t_function ) && !type.checkBit( TypeInfo.isStatic ) ){
addThis( obj );
}
}
@ -459,7 +468,7 @@ public class ParserSymbolTable {
Declaration decl = (Declaration) _contextStack.peek();
Declaration containing = decl._containingScope;
//find innermost enclosing namespace
while( containing != null && containing.getType() != Declaration.t_namespace ){
while( containing != null && containing.getType() != TypeInfo.t_namespace ){
containing = containing._containingScope;
}
@ -482,17 +491,18 @@ public class ParserSymbolTable {
* of this is volatile X*....
*/
private void addThis( Declaration obj ) throws ParserSymbolTableException{
if( obj.getType() != Declaration.t_function || obj.isStatic() ){
TypeInfo type = obj._typeInfo;
if( !type.isType( TypeInfo.t_function ) || type.checkBit( TypeInfo.isStatic ) ){
return;
}
if( obj._containingScope.isType( Declaration.t_class, Declaration.t_union ) ){
if( obj._containingScope.isType( TypeInfo.t_class, TypeInfo.t_union ) ){
//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 ){
Declaration thisObj = new Declaration("this");
thisObj.setType( Declaration.t_type );
thisObj.setType( TypeInfo.t_type );
thisObj.setTypeDeclaration( obj._containingScope );
thisObj.setCVQualifier( obj.getCVQualifier() );
thisObj.setPtrOperator("*");
@ -513,7 +523,7 @@ public class ParserSymbolTable {
*/
static private Declaration Lookup( LookupData data, Declaration inDeclaration ) throws ParserSymbolTableException
{
if( data.type != -1 && data.type < Declaration.t_class && data.upperType > Declaration.t_union ){
if( data.type != -1 && data.type < TypeInfo.t_class && data.upperType > TypeInfo.t_union ){
throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTypeInfo );
}
@ -567,8 +577,8 @@ public class ParserSymbolTable {
}
}
decl = ResolveAmbiguities( data, foundNames );
if( decl != null ){
decl = ResolveAmbiguities( data, new HashSet( foundNames ) );
if( decl != null || data.stopAt == inDeclaration ){
return decl;
}
@ -664,7 +674,7 @@ public class ParserSymbolTable {
* Look for data.name in our collection _containedDeclarations
*/
private static Declaration LookupInContained( LookupData data, Declaration lookIn ) throws ParserSymbolTableException{
LinkedList found = null;
HashSet found = null;
Declaration temp = null;
Object obj = null;
@ -691,7 +701,7 @@ public class ParserSymbolTable {
return (Declaration) obj;
}
} else {
found = new LinkedList();
found = new HashSet();
LinkedList objList = (LinkedList)obj;
Iterator iter = objList.iterator();
@ -776,7 +786,9 @@ public class ParserSymbolTable {
} else if ( temp != null ) {
//it is not ambiguous if temp & decl are the same thing and it is static
//or an enumerator
if( decl == temp && ( temp.isStatic() || temp.getType() == Declaration.t_enumerator) ){
TypeInfo type = temp._typeInfo;
if( decl == temp && ( type.checkBit( TypeInfo.isStatic ) || type.isType( TypeInfo.t_enumerator ) ) ){
temp = null;
} else {
throw( new ParserSymbolTableException( ParserSymbolTableException.r_AmbiguousName ) );
@ -807,8 +819,8 @@ public class ParserSymbolTable {
int origType = origDecl.getType();
int newType = newDecl.getType();
if( (origType >= Declaration.t_class && origType <= Declaration.t_enumeration) && //class name or enumeration ...
( newType == Declaration.t_type || (newType >= Declaration.t_function && newType <= Declaration.typeMask) ) ){
if( (origType >= TypeInfo.t_class && origType <= TypeInfo.t_enumeration) && //class name or enumeration ...
( newType == TypeInfo.t_type || (newType >= TypeInfo.t_function && newType <= TypeInfo.typeMask) ) ){
return true;
}
@ -825,13 +837,13 @@ public class ParserSymbolTable {
//the first thing can be a class-name or enumeration name, but the rest
//must be functions. So make sure the newDecl is a function before even
//considering the list
if( newDecl.getType() != Declaration.t_function ){
if( newDecl.getType() != TypeInfo.t_function ){
return false;
}
Iterator iter = origList.iterator();
Declaration decl = (Declaration) iter.next();
boolean valid = (( decl.getType() >= Declaration.t_class && decl.getType() <= Declaration.t_enumeration ) ||
boolean valid = (( decl.getType() >= TypeInfo.t_class && decl.getType() <= TypeInfo.t_enumeration ) ||
isValidFunctionOverload( decl, newDecl ));
while( valid && iter.hasNext() ){
@ -847,14 +859,14 @@ public class ParserSymbolTable {
}
private static boolean isValidFunctionOverload( Declaration origDecl, Declaration newDecl ){
if( origDecl.getType() != Declaration.t_function || newDecl.getType() != Declaration.t_function ){
if( origDecl.getType() != TypeInfo.t_function || newDecl.getType() != TypeInfo.t_function ){
return false;
}
if( origDecl.hasSameParameters( newDecl ) ){
//functions with the same name and same parameter types cannot be overloaded if any of them
//is static
if( origDecl.isStatic() || newDecl.isStatic() ){
if( origDecl._typeInfo.checkBit( TypeInfo.isStatic ) || newDecl._typeInfo.checkBit( TypeInfo.isStatic ) ){
return false;
}
@ -870,54 +882,197 @@ public class ParserSymbolTable {
return true;
}
static private Declaration ResolveAmbiguities( LookupData data, LinkedList items ) throws ParserSymbolTableException{
Declaration decl = null;
static private Declaration ResolveAmbiguities( LookupData data, HashSet items ) throws ParserSymbolTableException{
int size = items.size();
Iterator iter = items.iterator();
if( size == 0){
return null;
} else if (size == 1) {
return (Declaration) items.getFirst();
return (Declaration) iter.next();
} else {
Declaration first = (Declaration)items.removeFirst();
//if first one is a class-name, the next ones hide it
if( first.getType() >= Declaration.t_class && first.getType() <= Declaration.t_enumeration ){
return ResolveAmbiguities( data, items );
}
//else, if the first is an object (ie not a function), the rest must be the same
//declaration. otherwise (ie it is a function), the rest must be functions.
boolean needSame = ( first.getType() != Declaration.t_function );
Iterator iter = items.iterator();
for( int i = (size - 1); i > 0; i-- ){
decl = (Declaration) iter.next();
LinkedList functionList = null;
Declaration decl = null;
Declaration obj = null;
Declaration cls = null;
if( needSame ){
if( decl != first ){
throw new ParserSymbolTableException( ParserSymbolTableException.r_AmbiguousName );
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( decl.getType() != Declaration.t_function ){
throw new ParserSymbolTableException( ParserSymbolTableException.r_AmbiguousName );
//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( needSame ){
return first;
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;
}
}
}
}
if( obj != null && !ambiguous ){
if( numFunctions > 0 ){
ambiguous = true;
} else {
return obj;
}
} else if( numFunctions > 0 ) {
return ResolveFunction( data, functionList );
}
if( ambiguous ){
throw new ParserSymbolTableException( ParserSymbolTableException.r_AmbiguousName );
} else {
items.addFirst( first );
return ResolveFunction( data, items );
return cls;
}
}
}
static private Declaration ResolveFunction( LookupData data, LinkedList functions ){
static private Declaration ResolveFunction( LookupData data, LinkedList functions ) throws ParserSymbolTableException{
ReduceToViable( data, functions );
int numSourceParams = ( data.parameters == null ) ? 0 : data.parameters.size();
int numFns = functions.size();
if( numSourceParams == 0 ){
//no parameters
//if there is only 1 viable function, return it, if more than one, its ambiguous
if( numFns == 0 ){
return null;
} else if ( numFns == 1 ){
return (Declaration)functions.getFirst();
} else{
throw new ParserSymbolTableException( ParserSymbolTableException.r_AmbiguousName );
}
}
Declaration bestFn = null; //the best function
Declaration currFn = null; //the function currently under consideration
int [] bestFnCost = null; //the cost of the best function
int [] currFnCost = null; //the cost for the current function
Iterator iterFns = functions.iterator();
Iterator sourceParams = null;
Iterator targetParams = null;
int numTargetParams = 0;
int numParams = 0;
int cost, temp, comparison;
TypeInfo source = null;
TypeInfo target = null;
for( int i = numFns; i > 0; i-- ){
currFn = (Declaration) iterFns.next();
sourceParams = data.parameters.iterator();
targetParams = currFn._parameters.iterator();
//number of parameters in the current function
numTargetParams = currFn._parameters.size();
//we only need to look at the smaller number of parameters
//(a larger number in the Target means default parameters, a larger
//number in the source means ellipses.)
numParams = ( numTargetParams < numSourceParams ) ? numTargetParams : numSourceParams;
if( currFnCost == null ){
currFnCost = new int [ numParams ];
}
comparison = 0;
for( int j = 0; j < numParams; j++ ){
source = ( TypeInfo )sourceParams.next();
target = ( TypeInfo )targetParams.next();
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
}
}
currFnCost[ j ] = cost;
//compare successes against the best function
//comparison = (-1 = worse, 0 = same, 1 = better )
if( cost >= 0 ){
if( bestFnCost != null ){
if( cost < bestFnCost[ j ] ){
comparison = 1; //better
} else if ( cost > bestFnCost[ j ] ){
comparison = -1; //worse
break; //don't bother continuing if worse
}
} else {
comparison = 1;
}
} else {
comparison = -1;
}
}
if( comparison > 0){
//the current function is better than the previous best
bestFnCost = currFnCost;
currFnCost = null;
bestFn = currFn;
} else if( comparison == 0 ){
//this is just as good as the best one, which means the best one isn't the best
bestFn = null;
}
}
return bestFn;
}
static private void ReduceToViable( LookupData data, LinkedList functions ){
int numParameters = ( data.parameters == null ) ? 0 : data.parameters.size();
int num;
@ -931,7 +1086,7 @@ public class ParserSymbolTable {
//if there are m arguments in the list, all candidate functions having m parameters
//are viable
if( num == numParameters ){
continue;
continue;
}
//A candidate function having fewer than m parameters is viable only if it has an
//ellipsis in its parameter list.
@ -943,31 +1098,19 @@ public class ParserSymbolTable {
//a candidate function having more than m parameters is viable only if the (m+1)-st
//parameter has a default argument
else {
ListIterator listIter = function._parameters.listIterator( num - 1 );
Declaration.ParameterInfo param;
for( int i = num; i > ( numParameters - num ); i-- ){
param = (Declaration.ParameterInfo)listIter.previous();
if( !param.hasDefaultValue ){
iter.remove();
break;
ListIterator listIter = function._parameters.listIterator( num );
TypeInfo param;
for( int i = num; i > ( numParameters - num + 1); i-- ){
param = (TypeInfo)listIter.previous();
if( !param.getHasDefault() ){
iter.remove();
break;
}
}
}
}
//TBD, rank implicit conversion sequences to determine which one is best.
int size = functions.size();
if( size == 0 ){
return null;
}
else if( size == 1) {
return (Declaration) functions.getFirst();
}
return null;
}
/**
* function ProcessDirectives
* @param Declaration decl
@ -1044,13 +1187,20 @@ public class ParserSymbolTable {
*
* @param obj
* @param base
* @return boolean
* figure out if base is a base class of obj.
* @return int
* figure out if base is a base class of obj, and return the "distance" to
* the base class.
* ie:
* A -> B -> C
* the distance from A to B is 1 and from A to C is 2. This distance is used
* to rank standard pointer conversions.
*
* TBD: Consider rewriting iteratively for performance.
*/
static private boolean hasBaseClass( Declaration obj, Declaration base ){
boolean isABaseClass = false;
static private int hasBaseClass( Declaration obj, Declaration base ){
if( obj == base ){
return 0;
}
if( obj._parentScopes != null ){
Declaration decl;
@ -1063,13 +1213,19 @@ public class ParserSymbolTable {
wrapper = (Declaration.ParentWrapper) iter.next();
decl = wrapper.parent;
if( decl == base || hasBaseClass( decl, base ) ){
return true;
if( decl == base ){
return 1;
} else {
int n = hasBaseClass( decl, base );
if( n > 0 ){
return n + 1;
}
}
}
}
return false;
return -1;
}
static private void getAssociatedScopes( Declaration decl, HashSet associated ){
@ -1079,14 +1235,14 @@ public class ParserSymbolTable {
//if T is a class type, its associated classes are the class itself,
//and its direct and indirect base classes. its associated Namespaces are the
//namespaces in which its associated classes are defined
if( decl.getType() == Declaration.t_class ){
if( decl.getType() == TypeInfo.t_class ){
associated.add( decl );
getBaseClassesAndContainingNamespaces( decl, associated );
}
//if T is a union or enumeration type, its associated namespace is the namespace in
//which it is defined. if it is a class member, its associated class is the member's
//class
else if( decl.getType() == Declaration.t_union || decl.getType() == Declaration.t_enumeration ){
else if( decl.getType() == TypeInfo.t_union || decl.getType() == TypeInfo.t_enumeration ){
associated.add( decl._containingScope );
}
}
@ -1099,12 +1255,14 @@ public class ParserSymbolTable {
Iterator iter = obj._parentScopes.iterator();
int size = obj._parentScopes.size();
Declaration.ParentWrapper wrapper;
Declaration base;
for( int i = size; i > 0; i-- ){
base = (Declaration) iter.next();
wrapper = (Declaration.ParentWrapper) iter.next();
base = (Declaration) wrapper.parent;
classes.add( base );
if( base._containingScope.getType() == Declaration.t_namespace ){
if( base._containingScope.getType() == TypeInfo.t_namespace ){
classes.add( base._containingScope );
}
@ -1113,6 +1271,117 @@ public class ParserSymbolTable {
}
}
/**
*
* @param source
* @param target
* @return int
*
* 4.5-1 char, signed char, unsigned char, short int or unsigned short int
* can be converted to int if int can represent all the values of the source
* type, otherwise they can be converted to unsigned int.
* 4.5-2 wchar_t or an enumeration can be converted to the first of the
* following that can hold it: int, unsigned int, long unsigned long.
* 4.5-4 bool can be promoted to int
* 4.6 float can be promoted to double
*/
static private int canPromote( TypeInfo source, TypeInfo target ){
//if they are the same, no promotion is necessary
if( ( source.isType( TypeInfo.t_bool, TypeInfo.t_double ) ||
source.isType( TypeInfo.t_enumeration ) ) &&
source.getType() == target.getType() )
{
return 0;
}
if( source.isType( TypeInfo.t_enumeration ) || source.isType( TypeInfo.t_bool, TypeInfo.t_int ) ){
if( target.isType( TypeInfo.t_int ) && target.canHold( source ) ){
return 1;
}
} else if( source.isType( TypeInfo.t_float ) ){
if( target.isType( TypeInfo.t_double ) ){
return 1;
}
}
return -1;
}
/**
*
* @param source
* @param target
* @return int
*
*/
static private int canConvert(TypeInfo source, TypeInfo target ){
int temp = 0;
//are they the same?
if( source.getType() == target.getType() &&
source.getTypeDeclaration() == target.getTypeDeclaration() )
{
return 0;
}
//no go if they have different pointer qualification
if( ! source.getPtrOperator().equals( target.getPtrOperator() ) ){
return -1;
}
//TBD, do a better check on the kind of ptrOperator
if( !source.getPtrOperator().equals("*") ){
//4.7 An rvalue of an integer type can be converted to an rvalue of another integer type.
//An rvalue of an enumeration type can be converted to an rvalue of an integer type.
if( source.isType( TypeInfo.t_bool, TypeInfo.t_int ) ||
source.isType( TypeInfo.t_float, TypeInfo.t_double ) ||
source.isType( TypeInfo.t_enumeration ) )
{
if( target.isType( TypeInfo.t_bool, TypeInfo.t_int ) ||
target.isType( TypeInfo.t_float, TypeInfo.t_double ) )
{
return 2;
}
}
} else /*pointers*/ {
Declaration sourceDecl = source.getTypeDeclaration();
Declaration targetDecl = target.getTypeDeclaration();
//4.10-2 an rvalue of type "pointer to cv T", where T is an object type can be
//converted to an rvalue of type "pointer to cv void"
if( source.isType( TypeInfo.t_type ) && target.isType( TypeInfo.t_void ) ){
//use cost of MAX_VALUE since conversion to any base class, no matter how
//far away, would be better than conversion to void
return Integer.MAX_VALUE;
}
//4.10-3 An rvalue of type "pointer to cv D", where D is a class type can be converted
// to an rvalue of type "pointer to cv B", where B is a base class of D.
else if( source.isType( TypeInfo.t_type ) && sourceDecl.isType( TypeInfo.t_class ) &&
target.isType( TypeInfo.t_type ) && targetDecl.isType( TypeInfo.t_class ) )
{
temp = hasBaseClass( sourceDecl, targetDecl );
return ( temp > -1 ) ? 1 + temp : -1;
}
//4.11-2 An rvalue of type "pointer to member of B of type cv T", where B is a class type,
//can be converted to an rvalue of type "pointer to member of D of type cv T" where D is a
//derived class of B
else if( ( source.isType( TypeInfo.t_type ) && sourceDecl._containingScope.isType( TypeInfo.t_class ) ) ||
( target.isType( TypeInfo.t_type ) && targetDecl._containingScope.isType( TypeInfo.t_class ) ) )
{
temp = hasBaseClass( targetDecl._containingScope, sourceDecl._containingScope );
return ( temp > -1 ) ? 1 + temp : -1;
}
}
return -1;
}
static private boolean canDoQualificationConversion( TypeInfo source, TypeInfo target ){
return ( source.getCVQualifier() == source.getCVQualifier() ||
(source.getCVQualifier() - source.getCVQualifier()) > 1 );
}
private Stack _contextStack = new Stack();
private Declaration _compilationUnit;

View file

@ -0,0 +1,196 @@
/**********************************************************************
* Copyright (c) 2002,2003 Rational Software Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Common Public License v0.5
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/cpl-v05.html
*
* Contributors:
* Rational Software - Initial API and implementation
***********************************************************************/
package org.eclipse.cdt.internal.core.parser.util;
import org.eclipse.cdt.internal.core.parser.Declaration;
import org.eclipse.cdt.internal.core.parser.ParserSymbolTableException;
/**
* @author aniefer
*
* To change this generated comment edit the template variable "typecomment":
* Window>Preferences>Java>Templates.
* To enable and disable the creation of type comments go to
* Window>Preferences>Java>Code Generation.
*/
public class TypeInfo{
public TypeInfo(){
super();
}
public TypeInfo( int type, Declaration decl ){
super();
_typeInfo = type;
_typeDeclaration = decl;
}
public TypeInfo( int type, Declaration decl, int cvQualifier, String ptrOp, boolean hasDefault ){
super();
_typeInfo = type;
_typeDeclaration = decl;
_cvQualifier = cvQualifier;
_ptrOperator = ptrOp;
_hasDefaultValue = hasDefault;
}
public static final int typeMask = 0x001f;
public static final int isAuto = 0x0020;
public static final int isRegister = 0x0040;
public static final int isStatic = 0x0080;
public static final int isExtern = 0x0100;
public static final int isMutable = 0x0200;
public static final int isInline = 0x0400;
public static final int isVirtual = 0x0800;
public static final int isExplicit = 0x1000;
public static final int isTypedef = 0x2000;
public static final int isFriend = 0x4000;
public static final int isConst = 0x8000;
public static final int isVolatile = 0x10000;
public static final int isUnsigned = 0x20000;
public static final int isShort = 0x40000;
public static final int isLong = 0x80000;
// Types (maximum type is typeMask
// Note that these should be considered ordered and if you change
// the order, you should consider the ParserSymbolTable uses
public static final int t_type = 0; // Type Specifier
public static final int t_namespace = 1;
public static final int t_class = 2;
public static final int t_struct = 3;
public static final int t_union = 4;
public static final int t_enumeration = 5;
public static final int t_function = 6;
public static final int t_bool = 7;
public static final int t_char = 8;
public static final int t_wchar_t = 9;
public static final int t_int = 10;
public static final int t_float = 11;
public static final int t_double = 12;
public static final int t_void = 13;
public static final int t_enumerator = 14;
//Partial ordering :
// none < const
// none < volatile
// none < const volatile
// const < const volatile
// volatile < const volatile
public static final int cvConst = 1;
public static final int cvVolatile = 2;
public static final int cvConstVolatile = 4;
// Convenience methods
public void setBit(boolean b, int mask){
if( b ){
_typeInfo = _typeInfo | mask;
} else {
_typeInfo = _typeInfo & ~mask;
}
}
public boolean checkBit(int mask){
return (_typeInfo & mask) != 0;
}
public void setType(int t) throws ParserSymbolTableException{
//sanity check, t must fit in its allocated 5 bits in _typeInfo
if( t > typeMask ){
throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTypeInfo );
}
_typeInfo = _typeInfo & ~typeMask | t;
}
public int getType(){
return _typeInfo & typeMask;
}
public boolean isType( int type ){
return isType( type, 0 );
}
/**
*
* @param type
* @param upperType
* @return boolean
*
* type checking, check that this declaration's type is between type and
* upperType (inclusive). upperType of 0 means no range and our type must
* be type.
*/
public boolean isType( int type, int upperType ){
//type of -1 means we don't care
if( type == -1 )
return true;
//upperType of 0 means no range
if( upperType == 0 ){
return ( getType() == type );
} else {
return ( getType() >= type && getType() <= upperType );
}
}
public Declaration getTypeDeclaration(){
return _typeDeclaration;
}
public void setTypeDeclaration( Declaration type ){
_typeDeclaration = type;
}
public int getCVQualifier(){
return _cvQualifier;
}
public void setCVQualifier( int cv ){
_cvQualifier = cv;
}
public String getPtrOperator(){
return _ptrOperator;
}
public void setPtrOperator( String ptr ){
_ptrOperator = ptr;
}
public boolean getHasDefault(){
return _hasDefaultValue;
}
public void setHasDefault( boolean def ){
_hasDefaultValue = def;
}
/**
* canHold
* @param type
* @return boolean
* return true is the our type can hold all the values of the passed in
* type.
* TBD, for now return true if our type is "larger" (based on ordering of
* the type values)
*/
public boolean canHold( TypeInfo type ){
return getType() >= type.getType();
}
private int _typeInfo = 0;
private Declaration _typeDeclaration;
private int _cvQualifier = 0;
private boolean _hasDefaultValue = false;
private String _ptrOperator;
}

View file

@ -1,3 +1,8 @@
2003-03-26 Andrew Niefer
In ParserSymbolTableTest :
updated all tests to reflect TypeInfo changes
Added testFunctionResolution() & testFunctionResolution_2() in
2003-03-25 John Camelon
Added testDeclSpecifier(), testNamespaceDefinition(), testLinkageSpecification(),
testUsingClauses() and testEnumSpecifier() to DOMTests.

View file

@ -20,6 +20,7 @@ import junit.framework.TestCase;
import org.eclipse.cdt.internal.core.parser.Declaration;
import org.eclipse.cdt.internal.core.parser.ParserSymbolTable;
import org.eclipse.cdt.internal.core.parser.ParserSymbolTableException;
import org.eclipse.cdt.internal.core.parser.util.TypeInfo;
/**
* @author aniefer
@ -379,13 +380,13 @@ public class ParserSymbolTableTest extends TestCase {
table.addDeclaration( d );
Declaration enum = new Declaration("enum");
enum.setType( Declaration.t_enumeration );
enum.setType( TypeInfo.t_enumeration );
Declaration enumerator = new Declaration( "enumerator" );
enumerator.setType( Declaration.t_enumerator );
enumerator.setType( TypeInfo.t_enumerator );
Declaration stat = new Declaration("static");
stat.setStatic(true);
stat.getTypeInfo().setBit( true, TypeInfo.isStatic );
Declaration x = new Declaration("x");
@ -438,13 +439,13 @@ public class ParserSymbolTableTest extends TestCase {
newTable();
Declaration cls = new Declaration( "class" );
cls.setType( Declaration.t_class );
cls.setType( TypeInfo.t_class );
Declaration struct = new Declaration("struct");
struct.setType( Declaration.t_struct );
struct.setType( TypeInfo.t_struct );
Declaration union = new Declaration("union");
union.setType( Declaration.t_union );
union.setType( TypeInfo.t_union );
Declaration hideCls = new Declaration( "class" );
Declaration hideStruct = new Declaration("struct");
@ -466,11 +467,11 @@ public class ParserSymbolTableTest extends TestCase {
table.addDeclaration(union);
table.pop();
Declaration look = table.ElaboratedLookup( Declaration.t_class, "class" );
Declaration look = table.ElaboratedLookup( TypeInfo.t_class, "class" );
assertEquals( look, cls );
look = table.ElaboratedLookup( Declaration.t_struct, "struct" );
look = table.ElaboratedLookup( TypeInfo.t_struct, "struct" );
assertEquals( look, struct );
look = table.ElaboratedLookup( Declaration.t_union, "union" );
look = table.ElaboratedLookup( TypeInfo.t_union, "union" );
assertEquals( look, union );
}
@ -528,19 +529,19 @@ public class ParserSymbolTableTest extends TestCase {
newTable();
Declaration struct = new Declaration( "stat");
struct.setType( Declaration.t_struct );
struct.setType( TypeInfo.t_struct );
table.addDeclaration( struct );
Declaration function = new Declaration( "stat" );
function.setType( Declaration.t_function );
function.setType( TypeInfo.t_function );
table.addDeclaration( function );
Declaration f = new Declaration("f");
f.setType( Declaration.t_function );
f.setType( TypeInfo.t_function );
table.addDeclaration( f );
table.push( f );
Declaration look = table.ElaboratedLookup( Declaration.t_struct, "stat" );
Declaration look = table.ElaboratedLookup( TypeInfo.t_struct, "stat" );
assertEquals( look, struct );
look = table.Lookup( "stat" );
@ -582,7 +583,7 @@ public class ParserSymbolTableTest extends TestCase {
newTable();
Declaration nsA = new Declaration("A");
nsA.setType( Declaration.t_namespace );
nsA.setType( TypeInfo.t_namespace );
table.addDeclaration( nsA );
table.push( nsA );
@ -590,12 +591,12 @@ public class ParserSymbolTableTest extends TestCase {
table.addDeclaration( nsA_i );
Declaration nsB = new Declaration("B");
nsB.setType( Declaration.t_namespace );
nsB.setType( TypeInfo.t_namespace );
table.addDeclaration( nsB );
table.push( nsB );
Declaration nsC = new Declaration("C");
nsC.setType( Declaration.t_namespace );
nsC.setType( TypeInfo.t_namespace );
table.addDeclaration( nsC );
table.push( nsC );
@ -607,7 +608,7 @@ public class ParserSymbolTableTest extends TestCase {
table.addUsingDirective( look );
Declaration f1 = new Declaration("f");
f1.setType( Declaration.t_function );
f1.setType( TypeInfo.t_function );
table.push( f1 );
look = table.Lookup( "i" );
@ -619,7 +620,7 @@ public class ParserSymbolTableTest extends TestCase {
assertEquals( table.peek(), nsA );
Declaration nsD = new Declaration("D");
nsD.setType( Declaration.t_namespace );
nsD.setType( TypeInfo.t_namespace );
table.addDeclaration( nsD );
table.push( nsD );
@ -632,7 +633,7 @@ public class ParserSymbolTableTest extends TestCase {
table.addUsingDirective( look );
Declaration f2 = new Declaration( "f2" );
f2.setType( Declaration.t_function );
f2.setType( TypeInfo.t_function );
table.addDeclaration( f2 );
table.push( f2 );
@ -650,7 +651,7 @@ public class ParserSymbolTableTest extends TestCase {
table.pop(); //end nsD
Declaration f3 = new Declaration ("f3");
f3.setType( Declaration.t_function );
f3.setType( TypeInfo.t_function );
table.addDeclaration( f3 );
table.push( f3 );
@ -661,7 +662,7 @@ public class ParserSymbolTableTest extends TestCase {
table.pop();
Declaration f4 = new Declaration ("f4");
f4.setType( Declaration.t_function );
f4.setType( TypeInfo.t_function );
table.addDeclaration( f4 );
table.push( f4 );
@ -693,7 +694,7 @@ public class ParserSymbolTableTest extends TestCase {
newTable();
Declaration nsM = new Declaration( "M" );
nsM.setType( Declaration.t_namespace );
nsM.setType( TypeInfo.t_namespace );
table.addDeclaration( nsM );
@ -703,7 +704,7 @@ public class ParserSymbolTableTest extends TestCase {
table.pop();
Declaration nsN = new Declaration( "N" );
nsN.setType( Declaration.t_namespace );
nsN.setType( TypeInfo.t_namespace );
table.addDeclaration( nsN );
@ -765,7 +766,7 @@ public class ParserSymbolTableTest extends TestCase {
newTable();
Declaration nsA = new Declaration("A");
nsA.setType( Declaration.t_namespace );
nsA.setType( TypeInfo.t_namespace );
table.addDeclaration( nsA );
table.push( nsA );
@ -774,21 +775,21 @@ public class ParserSymbolTableTest extends TestCase {
table.pop();
Declaration nsB = new Declaration("B");
nsB.setType( Declaration.t_namespace );
nsB.setType( TypeInfo.t_namespace );
table.addDeclaration( nsB );
table.push( nsB );
table.addUsingDirective( nsA );
table.pop();
Declaration nsC = new Declaration("C");
nsC.setType( Declaration.t_namespace );
nsC.setType( TypeInfo.t_namespace );
table.addDeclaration( nsC );
table.push( nsC );
table.addUsingDirective( nsA );
table.pop();
Declaration nsBC = new Declaration("BC");
nsBC.setType( Declaration.t_namespace );
nsBC.setType( TypeInfo.t_namespace );
table.addDeclaration( nsBC );
table.push( nsBC );
table.addUsingDirective( nsB );
@ -796,7 +797,7 @@ public class ParserSymbolTableTest extends TestCase {
table.pop();
Declaration f = new Declaration("f");
f.setType(Declaration.t_function);
f.setType(TypeInfo.t_function);
table.addDeclaration( f );
table.push(f);
@ -834,7 +835,7 @@ public class ParserSymbolTableTest extends TestCase {
newTable();
Declaration nsB = new Declaration( "B" );
nsB.setType( Declaration.t_namespace );
nsB.setType( TypeInfo.t_namespace );
table.addDeclaration( nsB );
table.push( nsB );
@ -843,7 +844,7 @@ public class ParserSymbolTableTest extends TestCase {
table.pop();
Declaration nsA = new Declaration( "A" );
nsA.setType( Declaration.t_namespace );
nsA.setType( TypeInfo.t_namespace );
table.addDeclaration( nsA );
table.push( nsA );
@ -908,11 +909,11 @@ public class ParserSymbolTableTest extends TestCase {
newTable();
Declaration nsA = new Declaration( "A" );
nsA.setType( Declaration.t_namespace );
nsA.setType( TypeInfo.t_namespace );
table.addDeclaration( nsA );
Declaration nsB = new Declaration( "B" );
nsB.setType( Declaration.t_namespace );
nsB.setType( TypeInfo.t_namespace );
table.addDeclaration( nsB );
table.push( nsB );
table.addUsingDirective( nsA );
@ -961,39 +962,39 @@ public class ParserSymbolTableTest extends TestCase {
newTable();
Declaration nsA = new Declaration("A");
nsA.setType( Declaration.t_namespace );
nsA.setType( TypeInfo.t_namespace );
table.addDeclaration( nsA );
table.push( nsA );
Declaration structX = new Declaration("x");
structX.setType( Declaration.t_struct );
structX.setType( TypeInfo.t_struct );
table.addDeclaration( structX );
Declaration intX = new Declaration("x");
intX.setType( Declaration.t_int );
intX.setType( TypeInfo.t_int );
table.addDeclaration( intX );
Declaration intY = new Declaration("y");
intY.setType( Declaration.t_int );
intY.setType( TypeInfo.t_int );
table.addDeclaration( intY );
table.pop();
Declaration nsB = new Declaration("B");
nsB.setType( Declaration.t_namespace );
nsB.setType( TypeInfo.t_namespace );
table.addDeclaration( nsB );
table.push( nsB );
Declaration structY = new Declaration("y");
structY.setType( Declaration.t_struct );
structY.setType( TypeInfo.t_struct );
table.addDeclaration( structY );
table.pop();
Declaration nsC = new Declaration("C");
nsC.setType( Declaration.t_namespace);
nsC.setType( TypeInfo.t_namespace);
table.addDeclaration( nsC );
table.push( nsC );
@ -1044,17 +1045,17 @@ public class ParserSymbolTableTest extends TestCase {
newTable();
Declaration nsA = new Declaration( "A" );
nsA.setType( Declaration.t_namespace );
nsA.setType( TypeInfo.t_namespace );
table.addDeclaration( nsA );
table.push( nsA );
Declaration nsB = new Declaration( "B" );
nsB.setType( Declaration.t_namespace );
nsB.setType( TypeInfo.t_namespace );
table.addDeclaration( nsB );
table.push( nsB );
Declaration f1 = new Declaration("f1");
f1.setType( Declaration.t_function );
f1.setType( TypeInfo.t_function );
table.addDeclaration( f1 );
table.pop();
@ -1102,21 +1103,21 @@ public class ParserSymbolTableTest extends TestCase {
newTable();
Declaration B = new Declaration("B");
B.setType( Declaration.t_struct );
B.setType( TypeInfo.t_struct );
table.addDeclaration( B );
table.push( B );
Declaration f = new Declaration("f");
f.setType( Declaration.t_function );
f.setType( TypeInfo.t_function );
table.addDeclaration( f );
Declaration E = new Declaration( "E" );
E.setType( Declaration.t_enumeration );
E.setType( TypeInfo.t_enumeration );
table.addDeclaration( E );
table.push( E );
Declaration e = new Declaration( "e" );
e.setType( Declaration.t_enumerator );
e.setType( TypeInfo.t_enumerator );
table.addDeclaration( e );
table.pop();
@ -1125,17 +1126,17 @@ public class ParserSymbolTableTest extends TestCase {
table.pop();
Declaration C = new Declaration( "C" );
C.setType( Declaration.t_class );
C.setType( TypeInfo.t_class );
table.addDeclaration( C );
table.push( C );
Declaration g = new Declaration( "g" );
g.setType( Declaration.t_function );
g.setType( TypeInfo.t_function );
table.addDeclaration( g );
table.pop();
Declaration D = new Declaration( "D" );
D.setType( Declaration.t_struct );
D.setType( TypeInfo.t_struct );
Declaration look = table.Lookup( "B" );
assertEquals( look, B );
D.addParent( look );
@ -1212,15 +1213,15 @@ public class ParserSymbolTableTest extends TestCase {
newTable();
Declaration A = new Declaration( "A" );
A.setType( Declaration.t_namespace );
A.setType( TypeInfo.t_namespace );
table.addDeclaration( A );
table.push( A );
Declaration f1 = new Declaration( "f" );
f1.setType( Declaration.t_function );
f1.setReturnType( Declaration.t_void );
f1.addParameter( Declaration.t_int, "", false );
f1.setType( TypeInfo.t_function );
f1.setReturnType( TypeInfo.t_void );
f1.addParameter( TypeInfo.t_int, 0, "", false );
table.addDeclaration( f1 );
table.pop();
@ -1239,21 +1240,20 @@ public class ParserSymbolTableTest extends TestCase {
table.push( look );
Declaration f2 = new Declaration("f");
f2.setType( Declaration.t_function );
f2.setReturnType( Declaration.t_void );
f2.addParameter( Declaration.t_char, "", false );
f2.setType( TypeInfo.t_function );
f2.setReturnType( TypeInfo.t_void );
f2.addParameter( TypeInfo.t_char, 0, "", false );
table.addDeclaration( f2 );
table.pop();
Declaration foo = new Declaration("foo");
foo.setType( Declaration.t_function );
foo.setType( TypeInfo.t_function );
table.addDeclaration( foo );
table.push( foo );
LinkedList paramList = new LinkedList();
Declaration.ParameterInfo param = foo.new ParameterInfo();
param.typeInfo = Declaration.t_char;
TypeInfo param = new TypeInfo( TypeInfo.t_char, null );
paramList.add( param );
look = table.UnqualifiedFunctionLookup( "f", paramList );
@ -1273,11 +1273,11 @@ public class ParserSymbolTableTest extends TestCase {
newTable();
Declaration cls = new Declaration("class");
cls.setType( Declaration.t_class );
cls.setType( TypeInfo.t_class );
Declaration fn = new Declaration("function");
fn.setType( Declaration.t_function );
fn.setCVQualifier("const");
fn.setType( TypeInfo.t_function );
fn.setCVQualifier( TypeInfo.cvConst );
table.addDeclaration( cls );
table.push( cls );
@ -1288,7 +1288,7 @@ public class ParserSymbolTableTest extends TestCase {
Declaration look = table.Lookup("this");
assertTrue( look != null );
assertEquals( look.getType(), Declaration.t_type );
assertEquals( look.getType(), TypeInfo.t_type );
assertEquals( look.getTypeDeclaration(), cls );
assertEquals( look.getPtrOperator(), "*" );
assertEquals( look.getCVQualifier(), fn.getCVQualifier() );
@ -1307,10 +1307,10 @@ public class ParserSymbolTableTest extends TestCase {
newTable();
Declaration cls = new Declaration("class");
cls.setType( Declaration.t_class );
cls.setType( TypeInfo.t_class );
Declaration enumeration = new Declaration("enumeration");
enumeration.setType( Declaration.t_enumeration );
enumeration.setType( TypeInfo.t_enumeration );
table.addDeclaration( cls );
table.push( cls );
@ -1318,7 +1318,7 @@ public class ParserSymbolTableTest extends TestCase {
table.push( enumeration );
Declaration enumerator = new Declaration( "enumerator" );
enumerator.setType( Declaration.t_enumerator );
enumerator.setType( TypeInfo.t_enumerator );
table.addDeclaration( enumerator );
table.pop();
@ -1346,23 +1346,23 @@ public class ParserSymbolTableTest extends TestCase {
newTable();
Declaration NS = new Declaration("NS");
NS.setType( Declaration.t_namespace );
NS.setType( TypeInfo.t_namespace );
table.addDeclaration( NS );
table.push( NS );
Declaration T = new Declaration("T");
T.setType( Declaration.t_class );
T.setType( TypeInfo.t_class );
table.addDeclaration( T );
Declaration f = new Declaration("f");
f.setType( Declaration.t_function );
f.setReturnType( Declaration.t_void );
f.setType( TypeInfo.t_function );
f.setReturnType( TypeInfo.t_void );
Declaration look = table.Lookup( "T" );
assertEquals( look, T );
f.addParameter( look, "", false );
f.addParameter( look, 0, "", false );
table.addDeclaration( f );
@ -1376,13 +1376,13 @@ public class ParserSymbolTableTest extends TestCase {
table.pop();
Declaration param = new Declaration("parm");
param.setType( Declaration.t_type );
param.setType( TypeInfo.t_type );
param.setTypeDeclaration( look );
table.addDeclaration( param );
Declaration main = new Declaration("main");
main.setType( Declaration.t_function );
main.setReturnType( Declaration.t_int );
main.setType( TypeInfo.t_function );
main.setReturnType( TypeInfo.t_int );
table.addDeclaration( main );
table.push( main );
@ -1390,11 +1390,7 @@ public class ParserSymbolTableTest extends TestCase {
look = table.Lookup( "parm" );
assertEquals( look, param );
Declaration.ParameterInfo p = look.new ParameterInfo();
p.typeInfo = look.getType();
p.typeDeclaration = look.getTypeDeclaration();
paramList.add( p );
paramList.add( look.getTypeInfo() );
look = table.UnqualifiedFunctionLookup( "f", paramList );
assertEquals( look, f );
@ -1427,20 +1423,20 @@ public class ParserSymbolTableTest extends TestCase {
newTable();
Declaration NS1 = new Declaration( "NS1" );
NS1.setType( Declaration.t_namespace );
NS1.setType( TypeInfo.t_namespace );
table.addDeclaration( NS1 );
table.push( NS1 );
Declaration f1 = new Declaration( "f" );
f1.setType( Declaration.t_function );
f1.setReturnType( Declaration.t_void );
f1.addParameter( Declaration.t_void, "*", false );
f1.setType( TypeInfo.t_function );
f1.setReturnType( TypeInfo.t_void );
f1.addParameter( TypeInfo.t_void, 0, "*", false );
table.addDeclaration( f1 );
table.pop();
Declaration NS2 = new Declaration( "NS2" );
NS2.setType( Declaration.t_namespace );
NS2.setType( TypeInfo.t_namespace );
table.addDeclaration( NS2 );
table.push( NS2 );
@ -1450,18 +1446,18 @@ public class ParserSymbolTableTest extends TestCase {
table.addUsingDirective( look );
Declaration B = new Declaration( "B" );
B.setType( Declaration.t_class );
B.setType( TypeInfo.t_class );
table.addDeclaration( B );
Declaration f2 = new Declaration( "f" );
f2.setType( Declaration.t_function );
f2.setReturnType( Declaration.t_void );
f2.addParameter( Declaration.t_void, "*", false );
f2.setType( TypeInfo.t_function );
f2.setReturnType( TypeInfo.t_void );
f2.addParameter( TypeInfo.t_void, 0, "*", false );
table.addDeclaration( f2 );
table.pop();
Declaration A = new Declaration( "A" );
A.setType( Declaration.t_class );
A.setType( TypeInfo.t_class );
look = table.LookupNestedNameSpecifier( "NS2" );
assertEquals( look, NS2 );
table.push( look );
@ -1474,14 +1470,14 @@ public class ParserSymbolTableTest extends TestCase {
look = table.Lookup( "A" );
assertEquals( look, A );
Declaration a = new Declaration( "a" );
a.setType( Declaration.t_type );
a.setType( TypeInfo.t_type );
a.setTypeDeclaration( look );
table.addDeclaration( a );
LinkedList paramList = new LinkedList();
look = table.Lookup( "a" );
assertEquals( look, a );
Declaration.ParameterInfo param = look.new ParameterInfo( look.getType(), look, "&", false );
TypeInfo param = new TypeInfo( look.getType(), look, 0, "&", false );
paramList.add( param );
look = table.UnqualifiedFunctionLookup( "f", paramList );
@ -1517,24 +1513,24 @@ public class ParserSymbolTableTest extends TestCase {
table.push(C);
Declaration f1 = new Declaration("foo");
f1.setType( Declaration.t_function );
f1.setReturnType( Declaration.t_void );
f1.addParameter( Declaration.t_int, "", false );
f1.setType( TypeInfo.t_function );
f1.setReturnType( TypeInfo.t_void );
f1.addParameter( TypeInfo.t_int, 0, "", false );
table.addDeclaration( f1 );
Declaration f2 = new Declaration("foo");
f2.setType( Declaration.t_function );
f2.setReturnType( Declaration.t_void );
f2.addParameter( Declaration.t_int, "", false );
f2.addParameter( Declaration.t_char, "", false );
f2.setType( TypeInfo.t_function );
f2.setReturnType( TypeInfo.t_void );
f2.addParameter( TypeInfo.t_int, 0, "", false );
f2.addParameter( TypeInfo.t_char, 0, "", false );
table.addDeclaration( f2 );
Declaration f3 = new Declaration("foo");
f3.setType( Declaration.t_function );
f3.setReturnType( Declaration.t_void );
f3.addParameter( Declaration.t_int, "", false );
f3.addParameter( Declaration.t_char, "", false );
f3.addParameter( C, "*", false );
f3.setType( TypeInfo.t_function );
f3.setReturnType( TypeInfo.t_void );
f3.addParameter( TypeInfo.t_int, 0, "", false );
f3.addParameter( TypeInfo.t_char, 0, "", false );
f3.addParameter( C, 0, "*", false );
table.addDeclaration( f3 );
table.pop();
@ -1542,7 +1538,7 @@ public class ParserSymbolTableTest extends TestCase {
assertEquals( look, C );
Declaration c = new Declaration("c");
c.setType( Declaration.t_class );
c.setType( TypeInfo.t_class );
c.setTypeDeclaration( look );
table.addDeclaration( c );
@ -1552,9 +1548,9 @@ public class ParserSymbolTableTest extends TestCase {
table.push( look.getTypeDeclaration() );
LinkedList paramList = new LinkedList();
Declaration.ParameterInfo p1 = c.new ParameterInfo(Declaration.t_int, null, "", false);
Declaration.ParameterInfo p2 = c.new ParameterInfo(Declaration.t_char, null, "", false);
Declaration.ParameterInfo p3 = c.new ParameterInfo(Declaration.t_class, C, "", false);
TypeInfo p1 = new TypeInfo( TypeInfo.t_int, null, 0, "", false);
TypeInfo p2 = new TypeInfo( TypeInfo.t_char, null, 0, "", false);
TypeInfo p3 = new TypeInfo( TypeInfo.t_type, C, 0, "*", false);
paramList.add( p1 );
look = table.MemberFunctionLookup( "foo", paramList );
@ -1568,4 +1564,109 @@ public class ParserSymbolTableTest extends TestCase {
look = table.MemberFunctionLookup( "foo", paramList );
assertEquals( look, f3 );
}
/**
*
* @throws Exception
* test basic function resolution
*
* void f( int i );
* void f( char c = 'c' );
*
* f( 1 ); //calls f( int );
* f( 'b' ); //calls f( char );
* f(); //calls f( char );
*/
public void testFunctionResolution_1() throws Exception{
newTable();
Declaration f1 = new Declaration("f");
f1.setType( TypeInfo.t_function );
f1.addParameter( TypeInfo.t_int, 0, "", false );
table.addDeclaration( f1 );
Declaration f2 = new Declaration("f");
f2.setType( TypeInfo.t_function );
f2.addParameter( TypeInfo.t_char, 0, "", true );
table.addDeclaration( f2 );
LinkedList paramList = new LinkedList();
TypeInfo p1 = new TypeInfo( TypeInfo.t_int, null, 0, "", false );
paramList.add( p1 );
Declaration look = table.UnqualifiedFunctionLookup( "f", paramList );
assertEquals( look, f1 );
paramList.clear();
TypeInfo p2 = new TypeInfo( TypeInfo.t_char, null, 0, "", false );
paramList.add( p2 );
look = table.UnqualifiedFunctionLookup( "f", paramList );
assertEquals( look, f2 );
paramList.clear();
TypeInfo p3 = new TypeInfo( TypeInfo.t_bool, null, 0, "", false );
paramList.add( p3 );
look = table.UnqualifiedFunctionLookup( "f", paramList );
assertEquals( look, f1 );
look = table.UnqualifiedFunctionLookup( "f", null );
assertEquals( look, f2 );
}
/**
*
* @throws Exception
*
* class A { };
* class B : public A {};
* class C : public B {};
*
* void f ( A * );
* void f ( B * );
*
* A* a = new A();
* C* c = new C();
*
* f( a ); //calls f( A * );
* f( c ); //calls f( B * );
*/
public void testFunctionResolution_2() 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 );
B.addParent( A );
table.addDeclaration( B );
Declaration C = new Declaration( "C" );
C.setType( TypeInfo.t_class );
C.addParent( B );
table.addDeclaration( C );
Declaration f1 = new Declaration( "f" );
f1.setType( TypeInfo.t_function );
f1.addParameter( A, 0, "*", false );
table.addDeclaration( f1 );
Declaration f2 = new Declaration( "f" );
f2.setType( TypeInfo.t_function );
f2.addParameter( B, 0, "*", false );
table.addDeclaration( f2 );
LinkedList paramList = new LinkedList();
TypeInfo p1 = new TypeInfo( TypeInfo.t_type, A, 0, "*", false );
paramList.add( p1 );
Declaration look = table.UnqualifiedFunctionLookup( "f", paramList );
assertEquals( look, f1 );
paramList.clear();
TypeInfo p2 = new TypeInfo( TypeInfo.t_type, C, 0, "*", false );
paramList.add( p2 );
look = table.UnqualifiedFunctionLookup( "f", paramList );
assertEquals( look, f2 );
}
}