diff --git a/core/org.eclipse.cdt.core/parser/ChangeLog b/core/org.eclipse.cdt.core/parser/ChangeLog index 34bd581db7f..ee5764842dd 100644 --- a/core/org.eclipse.cdt.core/parser/ChangeLog +++ b/core/org.eclipse.cdt.core/parser/ChangeLog @@ -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. diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Declaration.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Declaration.java index f50df25cb98..2eb9fbcf580 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Declaration.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Declaration.java @@ -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; - } } diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTable.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTable.java index b75d62d5117..b5804acbc67 100644 --- a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTable.java +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTable.java @@ -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; diff --git a/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/util/TypeInfo.java b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/util/TypeInfo.java new file mode 100644 index 00000000000..0fe9b588529 --- /dev/null +++ b/core/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/util/TypeInfo.java @@ -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; +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui.tests/ChangeLog b/core/org.eclipse.cdt.ui.tests/ChangeLog index 650f86db45f..bd28b5a8aac 100644 --- a/core/org.eclipse.cdt.ui.tests/ChangeLog +++ b/core/org.eclipse.cdt.ui.tests/ChangeLog @@ -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. diff --git a/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java b/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java index d409456858b..a4df131ff5b 100644 --- a/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java +++ b/core/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java @@ -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 ); + } }