[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
[cdt-patch] Parser Symbol Table updates
|
Patch for the parser's symbol table.
-friends
-"this" pointer
-enumerators
-argument dependent lookup
-function parameters & function overloading
attached are:
patch_03.20.03(cdt.core).txt (changes)
patch_03.20.03(cdt.ui.tests).txt (junit tests)
-Andrew
Index: ChangeLog
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/parser/ChangeLog,v
retrieving revision 1.6
diff -u -r1.6 ChangeLog
--- ChangeLog 20 Mar 2003 15:13:09 -0000 1.6
+++ ChangeLog 20 Mar 2003 22:22:12 -0000
@@ -1,3 +1,11 @@
+2003-03-20 Andrew Niefer
+ Parser Symbol Table updates for:
+ * friends
+ * "this" pointer
+ * enumerators
+ * Argument dependent lookup
+ * adding parameters to functions & function overloading
+
2003-03-19 John Camelon
Updated Parser method visibility to solidify external interface.
Solved and removed TODO's from Scanner implementation.
Index: org/eclipse/cdt/internal/core/parser/Declaration.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/Declaration.java,v
retrieving revision 1.3
diff -u -r1.3 Declaration.java
--- org/eclipse/cdt/internal/core/parser/Declaration.java 6 Mar 2003 18:42:26 -0000 1.3
+++ org/eclipse/cdt/internal/core/parser/Declaration.java 20 Mar 2003 22:22:13 -0000
@@ -14,6 +14,7 @@
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
+import java.util.Iterator;
/**
* @author aniefer
@@ -24,7 +25,7 @@
* Window>Preferences>Java>Code Generation.
*/
-public class Declaration {
+public class Declaration implements Cloneable {
/**
* Constructor for Declaration.
@@ -42,6 +43,40 @@
_object = obj;
}
+ /**
+ * clone
+ * @see java.lang.Object#clone()
+ *
+ * implement clone for the purposes of using declarations.
+ * int _typeInfo; //by assignment
+ * String _name; //by assignment
+ * Object _object; //null this out
+ * Declaration _typeDeclaration; //by assignment
+ * Declaration _containingScope; //by assignment
+ * LinkedList _parentScopes; //shallow copy
+ * LinkedList _usingDirectives; //shallow copy
+ * HashMap _containedDeclarations; //shallow copy
+ * int _depth; //by assignment
+ */
+ public Object clone(){
+ Declaration copy = null;
+ try{
+ copy = (Declaration)super.clone();
+ }
+ catch ( CloneNotSupportedException e ){
+ //should not happen
+ return null;
+ }
+
+ copy._object = null;
+ copy._parentScopes = ( _parentScopes != null ) ? (LinkedList) _parentScopes.clone() : null;
+ copy._usingDirectives = ( _usingDirectives != null ) ? (LinkedList) _usingDirectives.clone() : null;
+ copy._containedDeclarations = ( _containedDeclarations != null ) ? (HashMap) _containedDeclarations.clone() : null;
+ copy._parameters = ( _parameters != null ) ? (LinkedList) _parameters.clone() : null;
+
+ return copy;
+ }
+
public static final int typeMask = 0x001f;
public static final int isAuto = 0x0020;
public static final int isRegister = 0x0040;
@@ -112,7 +147,7 @@
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_enum = 5;
+ 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;
@@ -169,13 +204,6 @@
}
public void setTypeDeclaration( Declaration type ){
- //setting our type to a declaration implies we are type t_type
- try {
- setType( t_type );
- } catch (ParserSymbolTableException e) {
- /*will never happen*/
- }
-
_typeDeclaration = type;
}
@@ -217,6 +245,93 @@
return _parentScopes;
}
+ public boolean needsDefinition(){
+ return _needsDefinition;
+ }
+ public void setNeedsDefinition( boolean need ) {
+ _needsDefinition = need;
+ }
+
+ public String getCVQualifier(){
+ return _cvQualifier;
+ }
+
+ public void setCVQualifier( String cv ){
+ _cvQualifier = cv;
+ }
+
+ public String getPtrOperator(){
+ return _ptrOperator;
+ }
+ public void setPtrOperator( String ptrOp ){
+ _ptrOperator = ptrOp;
+ }
+
+ public int getReturnType(){
+ return _returnType;
+ }
+
+ public void setReturnType( int type ){
+ _returnType = type;
+ }
+
+ public void addParameter( Declaration typeDecl, 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;
+
+ _parameters.add( info );
+ }
+
+ public void addParameter( int type, 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;
+
+ _parameters.add( info );
+ }
+
+ public boolean hasSameParameters( Declaration function ){
+ if( function.getType() != getType() ){
+ return false;
+ }
+
+ int size = _parameters.size();
+ if( function._parameters.size() != size ){
+ return false;
+ }
+
+ Iterator iter = _parameters.iterator();
+ Iterator fIter = function._parameters.iterator();
+
+ ParameterInfo info = null;
+ ParameterInfo fInfo = null;
+
+ for( int i = size; i > 0; i-- ){
+ info = (ParameterInfo) iter.next();
+ fInfo = (ParameterInfo) fIter.next();
+
+ if( !info.equals( fInfo ) ){
+ return false;
+ }
+ }
+
+
+ return true;
+ }
+
// Convenience methods
private void setBit(boolean b, int mask){
if( b ){
@@ -234,11 +349,16 @@
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 String _ptrOperator;
protected Declaration _containingScope; //the scope that contains us
protected LinkedList _parentScopes; //inherited scopes (is base classes)
protected LinkedList _usingDirectives; //collection of nominated namespaces
- protected Map _containedDeclarations; //declarations contained by us.
+ protected HashMap _containedDeclarations; //declarations contained by us.
+
+ protected LinkedList _parameters; //parameter list
+ protected int _returnType;
protected int _depth; //how far down the scope stack we are
@@ -253,4 +373,26 @@
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;
+ }
}
Index: org/eclipse/cdt/internal/core/parser/ParserSymbolTable.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTable.java,v
retrieving revision 1.3
diff -u -r1.3 ParserSymbolTable.java
--- org/eclipse/cdt/internal/core/parser/ParserSymbolTable.java 6 Mar 2003 18:42:26 -0000 1.3
+++ org/eclipse/cdt/internal/core/parser/ParserSymbolTable.java 20 Mar 2003 22:22:13 -0000
@@ -17,6 +17,7 @@
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
+import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
@@ -38,6 +39,12 @@
public ParserSymbolTable() {
super();
_compilationUnit = new Declaration();
+ try{
+ _compilationUnit.setType( Declaration.t_namespace );
+ } catch ( ParserSymbolTableException e ){
+ /*shouldn't happen*/
+ }
+
push( _compilationUnit );
}
@@ -86,8 +93,7 @@
return LookupNestedNameSpecifier( name, (Declaration) _contextStack.peek() );
}
- private Declaration LookupNestedNameSpecifier(String name, Declaration inDeclaration ) throws ParserSymbolTableException
- {
+ private Declaration LookupNestedNameSpecifier(String name, Declaration inDeclaration ) throws ParserSymbolTableException{
Declaration foundDeclaration = null;
LookupData data = new LookupData( name, Declaration.t_namespace );
@@ -103,25 +109,202 @@
}
/**
+ * LookupMemberForDefinition
+ * @param name
+ * @return Declaration
+ * @throws ParserSymbolTableException
+ *
+ * In a definition for a namespace member in which the declarator-id is a
+ * qualified-id, given that the qualified-id for the namespace member has
+ * the form "nested-name-specifier unqualified-id", the unqualified-id shall
+ * name a member of the namespace designated by the nested-name-specifier.
+ *
+ * ie:
+ * you have this:
+ * namespace A{
+ * namespace B{
+ * void f1(int);
+ * }
+ * using namespace B;
+ * }
+ *
+ * if you then do this
+ * void A::f1(int) { ... } //ill-formed, f1 is not a member of A
+ * but, you can do this (Assuming f1 has been defined elsewhere)
+ * A::f1( 1 ); //ok, finds B::f1
+ *
+ * ie, We need a seperate lookup function for looking up the member names
+ * for a definition.
+ */
+ public Declaration LookupMemberForDefinition( String name ) throws ParserSymbolTableException{
+ LookupData data = new LookupData( name, -1 );
+ data.qualified = true;
+
+ return LookupInContained( data, (Declaration) _contextStack.peek() );
+ }
+
+ /**
*
* @param name
* @return Declaration
* @throws ParserSymbolTableException
*
- * During lookup for a name preceding the :: scope resolution operator,
- * object, function, and enumerator names are ignored.
*/
- public Declaration QualifiedLookup( String name ) throws ParserSymbolTableException
- {
+ public Declaration QualifiedLookup( String name ) throws ParserSymbolTableException{
LookupData data = new LookupData( name, -1 );
data.qualified = true;
return Lookup( data, (Declaration) _contextStack.peek() );
}
- public void addUsingDirective( Declaration namespace ) throws ParserSymbolTableException
- {
+ /**
+ *
+ * @param name
+ * @param parameters
+ * @return Declaration
+ * @throws ParserSymbolTableException
+ */
+ public Declaration QualifiedFunctionLookup( String name, LinkedList parameters ) throws ParserSymbolTableException{
+ LookupData data = new LookupData( name, Declaration.t_function );
+ data.qualified = true;
+ data.parameters = parameters;
+
+ return Lookup( data, (Declaration) _contextStack.peek() );
+ }
+
+ /**
+ * MemberFunctionLookup
+ * @param name
+ * @param parameters
+ * @return Declaration
+ * @throws ParserSymbolTableException
+ *
+ * Member lookup really proceeds as an unqualified lookup, but doesn't
+ * include argument dependant scopes
+ */
+ public Declaration MemberFunctionLookup( String name, LinkedList parameters ) throws ParserSymbolTableException{
+ LookupData data = new LookupData( name, Declaration.t_function );
+ data.parameters = parameters;
+
+ return Lookup( data, (Declaration) _contextStack.peek() );
+ }
+
+ /**
+ * UnqualifiedFunctionLookup
+ * @param name
+ * @param parameters
+ * @return Declaration
+ * @throws ParserSymbolTableException
+ *
+ * 3.4.2-1 When an unqualified name is used as the post-fix expression in a
+ * function call, other namespaces not consdiered during the usual
+ * unqualified lookup may be searched.
+ *
+ * 3.4.2-2 For each argument type T in the function call, there is a set of
+ * zero or more associated namespaces and a set of zero or more associated
+ * classes to be considered.
+ *
+ * If the ordinary unqualified lookup of the name find the declaration of a
+ * class member function, the associated namespaces and classes are not
+ * considered. Otherwise, the set of declarations found by the lookup of
+ * the function name is the union of the set of declarations found using
+ * ordinary unqualified lookup and the set of declarations found in the
+ * namespaces and classes associated with the argument types.
+ */
+ public Declaration UnqualifiedFunctionLookup( String name, LinkedList parameters ) throws ParserSymbolTableException{
+ //figure out the set of associated scopes first, so we can remove those that are searched
+ //during the normal lookup to avoid doing them twice
+ HashSet associated = new HashSet();
+ //collect associated namespaces & classes.
+ int size = parameters.size();
+ Iterator iter = parameters.iterator();
+ Declaration.ParameterInfo param = null;
+ for( int i = size; i > 0; i-- ){
+ param = (Declaration.ParameterInfo) iter.next();
+
+ getAssociatedScopes( param.typeDeclaration, 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 ) )
+ {
+ getAssociatedScopes( param.typeDeclaration._containingScope, associated );
+ }
+ }
+
+ LookupData data = new LookupData( name, Declaration.t_function );
+ data.parameters = parameters;
+ data.associated = associated;
+
+ Declaration found = Lookup( data, (Declaration) _contextStack.peek() );
+
+ //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 ){
+ foundList.add( found );
+ }
+
+ iter = associated.iterator();
+
+ Declaration decl;
+ Declaration temp;
+
+ //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 );
+ }
+ }
+
+ found = ResolveAmbiguities( data, foundList );
+ }
+
+ return found;
+ }
+
+ /**
+ * LookupForFriendship
+ * @param name
+ * @return Declaration
+ * 7.3.1.2-3 When looking for a prior declaration of a class or a function
+ * declared as a friend, scopes outside the innermost enclosing namespace
+ * scope are not considered.
+ * 11.4-9 If a friend declaration appears in a local class and the name
+ * specified is an unqualified name, a prior declaration is looked up
+ * without considering scopes that are outside the innermost enclosing non-
+ * class scope.
+ */
+ private Declaration LookupForFriendship( String name ) throws ParserSymbolTableException{
+ LookupData data = new LookupData( name, -1 );
+
+ Declaration decl = (Declaration) _contextStack.peek();
+ boolean inClass = (decl.getType() == Declaration.t_class);
+
+ Declaration enclosing = decl._containingScope;
+ while( enclosing != null && (inClass ? enclosing.getType() != Declaration.t_class
+ : enclosing.getType() == Declaration.t_namespace) )
+ {
+ enclosing = enclosing._containingScope;
+ }
+
+ data.stopAt = enclosing;
+
+ return Lookup( data, (Declaration) _contextStack.peek() );
+ }
+
+ public void addUsingDirective( Declaration namespace ) throws ParserSymbolTableException{
if( namespace.getType() != Declaration.t_namespace ){
- throw new ParserSymbolTableException();
+ throw new ParserSymbolTableException( ParserSymbolTableException.r_BadTypeInfo );
}
Declaration declaration = (Declaration) _contextStack.peek();
@@ -133,10 +316,77 @@
declaration._usingDirectives.add( namespace );
}
+ /**
+ * addUsingDeclaration
+ * @param obj
+ * @throws ParserSymbolTableException
+ *
+ * 7.3.3-9 The entity declared by a using-declaration shall be known in the
+ * context using it according to its definition at the point of the using-
+ * declaration. Definitions added to the namespace after the using-
+ * declaration are not considered when a use of the name is made.
+ *
+ * 7.3.3-4 A using-declaration used as a member-declaration shall refer to a
+ * member of a base class of the class being defined, shall refer to a
+ * member of an anonymous union that is a member of a base class of the
+ * class being defined, or shall refer to an enumerator for an enumeration
+ * type that is a member of a base class of the class being defined.
+ */
+ public Declaration addUsingDeclaration( Declaration obj ) throws ParserSymbolTableException{
+ Declaration clone = null;
+ Declaration context = (Declaration) _contextStack.peek();
+ boolean okToAdd = false;
+
+ //7.3.3-4
+ if( context.isType( Declaration.t_class, Declaration.t_union ) ){
+ //a member of a base class
+ if( obj.getContainingScope().getType() == context.getType() ){
+ okToAdd = hasBaseClass( context, obj.getContainingScope() );
+ }
+ //TBD : a member of an _anonymous_ union
+ else if ( obj.getContainingScope().getType() == Declaration.t_union ) {
+ Declaration union = obj.getContainingScope();
+ okToAdd = hasBaseClass( context, union.getContainingScope() );
+ }
+ //an enumerator for an enumeration
+ else if ( obj.getType() == Declaration.t_enumerator ){
+ Declaration enumeration = obj.getContainingScope();
+ okToAdd = hasBaseClass( context, enumeration.getContainingScope() );
+ }
+ } else {
+ okToAdd = true;
+ }
+
+ if( okToAdd ){
+ clone = (Declaration) obj.clone(); //7.3.3-9
+ addDeclaration( clone );
+ } else {
+ throw new ParserSymbolTableException();
+ }
+ return clone;
+ }
+
public void addDeclaration( Declaration obj ) throws ParserSymbolTableException{
+
Declaration containing = (Declaration) _contextStack.peek();
+
+ //handle enumerators
+ if( obj.getType() == Declaration.t_enumerator ){
+ //a using declaration of an enumerator will not be contained in a
+ //enumeration.
+ if( containing.getType() == Declaration.t_enumeration ){
+ //Following the closing brace of an enum-specifier, each enumerator has the type of its
+ //enumeration
+ obj.setTypeDeclaration( containing );
+ //Each enumerator is declared in the scope that immediately contains the enum-specifier
+ containing = containing.getContainingScope();
+ }
+ }
+
Map declarations = containing.getContainedDeclarations();
+ boolean unnamed = obj.getName().equals( "" );
+
Object origObj = null;
obj.setContainingScope( containing );
@@ -161,7 +411,7 @@
throw new ParserSymbolTableException();
}
- if( (origList == null) ? isValidOverload( origDecl, obj ) : isValidOverload( origList, obj ) ){
+ if( unnamed || (origList == null) ? isValidOverload( origDecl, obj ) : isValidOverload( origList, obj ) ){
if( origList == null ){
origList = new LinkedList();
origList.add( origDecl );
@@ -174,11 +424,84 @@
//origList is already in _containedDeclarations
}
} else {
- throw new ParserSymbolTableException();
+ throw new ParserSymbolTableException( ParserSymbolTableException.r_InvalidOverload );
}
} else {
declarations.put( obj.getName(), obj );
}
+
+ //take care of the this pointer
+ if( obj.getType() == Declaration.t_function && !obj.isStatic() ){
+ addThis( obj );
+ }
+ }
+
+ /**
+ *
+ * @param name
+ * @return Declaration
+ * @throws ParserSymbolTableException
+ *
+ * 7.3.1.2-3 If a friend declaration in a non-local class first declares a
+ * class or function, the friend class or function is a member of the
+ * innermost enclosing namespace.
+ *
+ * TBD: if/when the parser symbol table starts caring about visibility
+ * (public/protected/private) we will need to do more to record friendship.
+ */
+ public Declaration addFriend( String name ) throws ParserSymbolTableException{
+ Declaration friend = LookupForFriendship( name );
+
+ if( friend == null ){
+ friend = new Declaration( name );
+ friend.setNeedsDefinition( true );
+
+ Declaration decl = (Declaration) _contextStack.peek();
+ Declaration containing = decl._containingScope;
+ //find innermost enclosing namespace
+ while( containing != null && containing.getType() != Declaration.t_namespace ){
+ containing = containing._containingScope;
+ }
+
+ Declaration namespace = (containing == null ) ? _compilationUnit : containing;
+ push( namespace );
+ addDeclaration( friend );
+ pop();
+ }
+
+ return friend;
+ }
+
+ /**
+ *
+ * @param obj
+ * @throws ParserSymbolTableException
+ * 9.3.2-1 In the body of a nonstatic member function... the type of this of
+ * a class X is X*. If the member function is declared const, the type of
+ * this is const X*, if the member function is declared volatile, the type
+ * of this is volatile X*....
+ */
+ private void addThis( Declaration obj ) throws ParserSymbolTableException{
+ if( obj.getType() != Declaration.t_function || obj.isStatic() ){
+ return;
+ }
+
+ if( obj._containingScope.isType( Declaration.t_class, Declaration.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.setTypeDeclaration( obj._containingScope );
+ thisObj.setCVQualifier( obj.getCVQualifier() );
+ thisObj.setPtrOperator("*");
+
+ push( obj );
+ addDeclaration( thisObj );
+ pop();
+ }
+ }
}
/**
@@ -206,43 +529,45 @@
foundNames.add( decl );
}
- //check nominated namespaces
- //the transitives list is populated in LookupInNominated, and then
- //processed in ProcessDirectives
-
- data.visited.clear(); //each namesapce is searched at most once, so keep track
-
- tempList = LookupInNominated( data, inDeclaration, transitives );
-
- if( tempList != null ){
- foundNames.addAll( tempList );
- }
+ if( !data.ignoreUsingDirectives ){
+ //check nominated namespaces
+ //the transitives list is populated in LookupInNominated, and then
+ //processed in ProcessDirectives
- //if we are doing a qualified lookup, only process using directives if
- //we haven't found the name yet.
- if( !data.qualified || foundNames.size() == 0 ){
- ProcessDirectives( inDeclaration, data, transitives );
+ data.visited.clear(); //each namesapce is searched at most once, so keep track
- if( inDeclaration._usingDirectives != null ){
- ProcessDirectives( inDeclaration, data, inDeclaration._usingDirectives );
+ tempList = LookupInNominated( data, inDeclaration, transitives );
+
+ if( tempList != null ){
+ foundNames.addAll( tempList );
}
-
- while( data.usingDirectives != null && data.usingDirectives.get( inDeclaration ) != null ){
- transitives.clear();
- tempList = LookupInNominated( data, inDeclaration, transitives );
+ //if we are doing a qualified lookup, only process using directives if
+ //we haven't found the name yet (and if we aren't ignoring them).
+ if( !data.qualified || foundNames.size() == 0 ){
+ ProcessDirectives( inDeclaration, data, transitives );
- if( tempList != null ){
- foundNames.addAll( tempList );
+ if( inDeclaration._usingDirectives != null ){
+ ProcessDirectives( inDeclaration, data, inDeclaration._usingDirectives );
}
-
- if( !data.qualified || foundNames.size() == 0 ){
- ProcessDirectives( inDeclaration, data, transitives );
+
+ while( data.usingDirectives != null && data.usingDirectives.get( inDeclaration ) != null ){
+ transitives.clear();
+
+ tempList = LookupInNominated( data, inDeclaration, transitives );
+
+ if( tempList != null ){
+ foundNames.addAll( tempList );
+ }
+
+ if( !data.qualified || foundNames.size() == 0 ){
+ ProcessDirectives( inDeclaration, data, transitives );
+ }
}
}
}
- decl = ResolveAmbiguities( foundNames );
+ decl = ResolveAmbiguities( data, foundNames );
if( decl != null ){
return decl;
}
@@ -343,6 +668,11 @@
Declaration temp = null;
Object obj = null;
+ if( data.associated != null ){
+ //we are looking in lookIn, remove it from the associated scopes list
+ data.associated.remove( lookIn );
+ }
+
Map declarations = lookIn.getContainedDeclarations();
if( declarations == null )
return null;
@@ -353,7 +683,7 @@
//not found
return null;
}
-
+
//the contained declarations map either to a Declaration object, or to a list
//of declaration objects.
if( obj.getClass() == Declaration.class ){
@@ -381,7 +711,7 @@
if( found == null || found.size() == 0 )
return null;
- return ResolveAmbiguities( found );
+ return ResolveAmbiguities( data, found );
}
/**
@@ -393,14 +723,21 @@
*/
private static Declaration LookupInParents( LookupData data, Declaration lookIn ) throws ParserSymbolTableException{
LinkedList scopes = lookIn.getParentScopes();
- Declaration decl = null;
Declaration temp = null;
+ Declaration decl = null;
+
Iterator iterator = null;
Declaration.ParentWrapper wrapper = null;
if( scopes == null )
return null;
+ //use data to detect circular inheritance
+ if( data.inheritanceChain == null )
+ data.inheritanceChain = new HashSet();
+
+ data.inheritanceChain.add( lookIn );
+
iterator = scopes.iterator();
int size = scopes.size();
@@ -413,15 +750,27 @@
data.visited.add( wrapper.parent );
}
- //is this name define in this scope?
- temp = LookupInContained( data, wrapper.parent );
+ //HashSet.add returns false if wrapper.parent is already in the set
+ //this means we have circular inheritance
+ if( data.inheritanceChain.add( wrapper.parent ) ){
+
+ //is this name define in this scope?
+ temp = LookupInContained( data, wrapper.parent );
- if( temp == null ){
- temp = LookupInParents( data, wrapper.parent );
+ if( temp == null ){
+ temp = LookupInParents( data, wrapper.parent );
+ }
+
+ data.inheritanceChain.remove( wrapper.parent );
+
+ } else {
+ throw new ParserSymbolTableException( ParserSymbolTableException.r_CircularInheritance );
}
+
}
if( temp != null && temp.isType( data.type ) ){
+
if( decl == null ){
decl = temp;
} else if ( temp != null ) {
@@ -458,18 +807,14 @@
int origType = origDecl.getType();
int newType = newDecl.getType();
- if( (origType >= Declaration.t_class && origType <= Declaration.t_enum) && //class name or enumeration ...
+ if( (origType >= Declaration.t_class && origType <= Declaration.t_enumeration) && //class name or enumeration ...
( newType == Declaration.t_type || (newType >= Declaration.t_function && newType <= Declaration.typeMask) ) ){
return true;
}
//if the origtype is not a class-name or enumeration name, then the only other
//allowable thing is if they are both functions.
- else if( origType == Declaration.t_function && newType == Declaration.t_function ){
- return true;
- }
-
- return false;
+ return isValidFunctionOverload( origDecl, newDecl );
}
private static boolean isValidOverload( LinkedList origList, Declaration newDecl ){
@@ -486,12 +831,12 @@
Iterator iter = origList.iterator();
Declaration decl = (Declaration) iter.next();
- boolean valid = (( decl.getType() >= Declaration.t_class && decl.getType() <= Declaration.t_enum ) ||
- decl.getType() == Declaration.t_function );
+ boolean valid = (( decl.getType() >= Declaration.t_class && decl.getType() <= Declaration.t_enumeration ) ||
+ isValidFunctionOverload( decl, newDecl ));
while( valid && iter.hasNext() ){
decl = (Declaration) iter.next();
- valid = ( decl.getType() == Declaration.t_function );
+ valid = isValidFunctionOverload( decl, newDecl );
}
return valid;
@@ -501,7 +846,31 @@
return true;
}
- static private Declaration ResolveAmbiguities( LinkedList items ) throws ParserSymbolTableException{
+ private static boolean isValidFunctionOverload( Declaration origDecl, Declaration newDecl ){
+ if( origDecl.getType() != Declaration.t_function || newDecl.getType() != Declaration.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() ){
+ return false;
+ }
+
+ //if none of them are static, then the function can be overloaded if they differ in the type
+ //of their implicit object parameter.
+ if( origDecl.getCVQualifier() != newDecl.getCVQualifier() ){
+ return true;
+ }
+
+ return false;
+ }
+
+ return true;
+ }
+
+ static private Declaration ResolveAmbiguities( LookupData data, LinkedList items ) throws ParserSymbolTableException{
Declaration decl = null;
int size = items.size();
@@ -514,8 +883,8 @@
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_enum ){
- return ResolveAmbiguities( items );
+ 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
@@ -529,11 +898,11 @@
if( needSame ){
if( decl != first ){
- throw new ParserSymbolTableException();
+ throw new ParserSymbolTableException( ParserSymbolTableException.r_AmbiguousName );
}
} else {
if( decl.getType() != Declaration.t_function ){
- throw new ParserSymbolTableException();
+ throw new ParserSymbolTableException( ParserSymbolTableException.r_AmbiguousName );
}
}
}
@@ -542,16 +911,63 @@
return first;
} else {
items.addFirst( first );
- return ResolveFunction( items );
+ return ResolveFunction( data, items );
}
}
}
- static private Declaration ResolveFunction( LinkedList functions ){
- //TBD
+ static private Declaration ResolveFunction( LookupData data, LinkedList functions ){
+
+ int numParameters = ( data.parameters == null ) ? 0 : data.parameters.size();
+ int num;
+
+ //Trim the list down to the set of viable functions
+ Declaration function;
+ Iterator iter = functions.iterator();
+ while( iter.hasNext() ){
+ function = (Declaration) iter.next();
+ num = ( function._parameters == null ) ? 0 : function._parameters.size();
+
+ //if there are m arguments in the list, all candidate functions having m parameters
+ //are viable
+ if( num == numParameters ){
+ continue;
+ }
+ //A candidate function having fewer than m parameters is viable only if it has an
+ //ellipsis in its parameter list.
+ else if( num < numParameters ) {
+ //TBD ellipsis
+ //not enough parameters, remove it
+ iter.remove();
+ }
+ //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;
+ }
+ }
+ }
+ }
+
+ //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
@@ -624,18 +1040,99 @@
}
}
+ /**
+ *
+ * @param obj
+ * @param base
+ * @return boolean
+ * figure out if base is a base class of obj.
+ *
+ * TBD: Consider rewriting iteratively for performance.
+ */
+ static private boolean hasBaseClass( Declaration obj, Declaration base ){
+ boolean isABaseClass = false;
+
+ if( obj._parentScopes != null ){
+ Declaration decl;
+ Declaration.ParentWrapper wrapper;
+
+ Iterator iter = obj._parentScopes.iterator();
+ int size = obj._parentScopes.size();
+
+ for( int i = size; i > 0; i-- ){
+ wrapper = (Declaration.ParentWrapper) iter.next();
+ decl = wrapper.parent;
+
+ if( decl == base || hasBaseClass( decl, base ) ){
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ static private void getAssociatedScopes( Declaration decl, HashSet associated ){
+ if( decl == null ){
+ return;
+ }
+ //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 ){
+ 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 ){
+ associated.add( decl._containingScope );
+ }
+ }
+
+ static private void getBaseClassesAndContainingNamespaces( Declaration obj, HashSet classes ){
+ if( obj._parentScopes != null ){
+ if( classes == null ){
+ return;
+ }
+
+ Iterator iter = obj._parentScopes.iterator();
+ int size = obj._parentScopes.size();
+ Declaration base;
+
+ for( int i = size; i > 0; i-- ){
+ base = (Declaration) iter.next();
+ classes.add( base );
+ if( base._containingScope.getType() == Declaration.t_namespace ){
+ classes.add( base._containingScope );
+ }
+
+ getBaseClassesAndContainingNamespaces( base, classes );
+ }
+ }
+ }
+
private Stack _contextStack = new Stack();
private Declaration _compilationUnit;
private class LookupData
{
+
public String name;
public Map usingDirectives;
public Set visited = new HashSet(); //used to ensure we don't visit things more than once
+ public HashSet inheritanceChain; //used to detect circular inheritance
+
+ public LinkedList parameters; //parameter info for resolving functions
+ public HashSet associated; //associated namespaces for argument dependant lookup
+ public Declaration stopAt; //stop looking along the stack once we hit this declaration
+
public int type = -1;
public int upperType = 0;
public boolean qualified = false;
+ public boolean ignoreUsingDirectives = false;
public LookupData( String n, int t ){
name = n;
Index: org/eclipse/cdt/internal/core/parser/ParserSymbolTableException.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/ParserSymbolTableException.java,v
retrieving revision 1.3
diff -u -r1.3 ParserSymbolTableException.java
--- org/eclipse/cdt/internal/core/parser/ParserSymbolTableException.java 6 Mar 2003 18:42:26 -0000 1.3
+++ org/eclipse/cdt/internal/core/parser/ParserSymbolTableException.java 20 Mar 2003 22:22:13 -0000
@@ -36,9 +36,11 @@
reason = r;
}
- public static final int r_Unspecified = -1;
- public static final int r_AmbiguousName = 0;
- public static final int r_BadTypeInfo = 1;
+ public static final int r_Unspecified = -1;
+ public static final int r_AmbiguousName = 0;
+ public static final int r_BadTypeInfo = 1;
+ public static final int r_CircularInheritance = 2;
+ public static final int r_InvalidOverload = 3;
public int reason = -1;
}
Index: org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.ui.tests/parser/org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java,v
retrieving revision 1.5
diff -u -r1.5 ParserSymbolTableTest.java
--- org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java 12 Mar 2003 15:35:35 -0000 1.5
+++ org/eclipse/cdt/core/parser/tests/ParserSymbolTableTest.java 20 Mar 2003 22:20:04 -0000
@@ -12,6 +12,7 @@
package org.eclipse.cdt.core.parser.tests;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.Map;
import junit.framework.TestCase;
@@ -244,6 +245,33 @@
}
/**
+ *
+ * @throws Exception
+ * test for circular inheritance
+ */
+ public void testCircularParentLookup() throws Exception{
+ newTable();
+
+ Declaration a = new Declaration("a");
+ table.addDeclaration( a );
+
+ Declaration b = new Declaration("b");
+ table.addDeclaration(b);
+
+ a.addParent( b );
+ b.addParent( a );
+
+ table.push( a );
+
+ try{
+ Declaration look = table.Lookup("foo");
+ assertTrue( false );
+ } catch ( ParserSymbolTableException e) {
+ assertEquals( e.reason, ParserSymbolTableException.r_CircularInheritance );
+ }
+
+ }
+ /**
* testVirtualParentLookup
*
* @throws Exception
@@ -320,7 +348,7 @@
assertTrue( false );
}
catch( ParserSymbolTableException e){
- assertTrue( true );
+ assertEquals( e.reason, ParserSymbolTableException.r_AmbiguousName );
}
}
@@ -351,7 +379,10 @@
table.addDeclaration( d );
Declaration enum = new Declaration("enum");
- enum.setType( Declaration.t_enumerator );
+ enum.setType( Declaration.t_enumeration );
+
+ Declaration enumerator = new Declaration( "enumerator" );
+ enumerator.setType( Declaration.t_enumerator );
Declaration stat = new Declaration("static");
stat.setStatic(true);
@@ -360,6 +391,9 @@
table.push(d);
table.addDeclaration( enum );
+ table.push( enum );
+ table.addDeclaration( enumerator );
+ table.pop();
table.addDeclaration( stat );
table.addDeclaration( x );
table.pop();
@@ -371,7 +405,7 @@
table.push( a );
try{
- table.Lookup( "enum" );
+ table.Lookup( "enumerator" );
assertTrue( true );
}
catch ( ParserSymbolTableException e){
@@ -391,7 +425,7 @@
assertTrue( false );
}
catch ( ParserSymbolTableException e){
- assertTrue( true );
+ assertEquals( e.reason, ParserSymbolTableException.r_AmbiguousName );
}
}
@@ -477,46 +511,6 @@
}
/**
- * testFunctions
- * @throws Exception
- * Functions are stored by signature. Where the signature can really be of
- * any for you like, as long as it can't possibly be a regular name (ie
- * including the parenthese is good...)
- * So lookup of function names proceeds inthe same manner as normal names,
- * this test doesn't really test anything new
- */
-
- public void testFunctions() throws Exception{
- newTable();
-
- Declaration cls = new Declaration( "class");
- Declaration f1 = new Declaration("foo()");
- Declaration f2 = new Declaration("foo(int)");
- Declaration f3 = new Declaration("foo(int,char)");
-
- table.addDeclaration(cls);
- table.push(cls);
-
- table.addDeclaration( f1 );
- table.addDeclaration( f2 );
- table.addDeclaration( f3 );
-
- //return type can be specified by setting the TypeDeclaration
- Declaration returnType = new Declaration("return");
- f1.setTypeDeclaration( returnType );
- f2.setTypeDeclaration( returnType );
- f3.setTypeDeclaration( returnType );
-
- assertEquals( table.Lookup("foo()"), f1 );
- assertEquals( table.Lookup("foo(int)"), f2 );
- assertEquals( table.Lookup("foo(int,char)"), f3 );
-
- //notice that, with the current implementation, you can't do a lookup
- //on just the function name without the rest of the signature
- assertEquals( table.Lookup("foo"), null );
- }
-
- /**
*
* @throws Exception
*
@@ -649,7 +643,8 @@
}
catch ( ParserSymbolTableException e )
{
- assertTrue(true); //ambiguous B::C::i and A::i
+ //ambiguous B::C::i and A::i
+ assertEquals( e.reason, ParserSymbolTableException.r_AmbiguousName );
}
table.pop(); //end f2
table.pop(); //end nsD
@@ -732,7 +727,8 @@
}
catch ( ParserSymbolTableException e )
{
- assertTrue( true ); //ambiguous, both M::i and N::i are visible.
+ //ambiguous, both M::i and N::i are visible.
+ assertEquals( e.reason, ParserSymbolTableException.r_AmbiguousName );
}
look = table.LookupNestedNameSpecifier("N");
@@ -1025,9 +1021,551 @@
try{
look = table.QualifiedLookup( "y" );
assertTrue(false);
- } catch ( Exception e ) {
- assertTrue(true);
+ } catch ( ParserSymbolTableException e ) {
+ assertEquals( e.reason, ParserSymbolTableException.r_AmbiguousName );
}
}
+ /**
+ * In a definition for a namespace member in which the declarator-id is a
+ * qualified-id, given that the qualified-id for the namespace member has
+ * the form "nested-name-specifier unqualified-id", the unqualified-id shall
+ * name a member of the namespace designated by the nested-name-specifier.
+ *
+ * namespace A{
+ * namespace B{
+ * void f1(int);
+ * }
+ * using namespace B;
+ * }
+ * void A::f1(int) { ... } //ill-formed, f1 is not a member of A
+ */
+ public void testLookupMemberForDefinition() throws Exception{
+ newTable();
+
+ Declaration nsA = new Declaration( "A" );
+ nsA.setType( Declaration.t_namespace );
+ table.addDeclaration( nsA );
+ table.push( nsA );
+
+ Declaration nsB = new Declaration( "B" );
+ nsB.setType( Declaration.t_namespace );
+ table.addDeclaration( nsB );
+ table.push( nsB );
+
+ Declaration f1 = new Declaration("f1");
+ f1.setType( Declaration.t_function );
+ table.addDeclaration( f1 );
+
+ table.pop();
+
+ table.addUsingDirective( nsB );
+ table.pop();
+
+ Declaration look = table.LookupNestedNameSpecifier( "A" );
+ assertEquals( nsA, look );
+ table.push( look );
+
+ look = table.LookupMemberForDefinition( "f1" );
+ assertEquals( look, null );
+
+ //but notice if you wanted to do A::f1 as a function call, it is ok
+ look = table.QualifiedLookup( "f1" );
+ assertEquals( look, f1 );
+ }
+
+ /**
+ * testUsingDeclaration
+ * @throws Exception
+ * 7.3.3-4 A using-declaration used as a member-declaration shall refer to a
+ * member of a base-class of the class being defined, shall refer to a
+ * member of an anonymous union that is a member of a base class of the
+ * class being defined or shall refer to an enumerator for an enumeration
+ * type that is a member of a base class of the class being defined
+ *
+ * struct B {
+ * void f( char );
+ * enum E { e };
+ * union { int x; };
+ * };
+ * class C {
+ * int g();
+ * }
+ * struct D : B {
+ * using B::f; //ok, B is a base class of D
+ * using B::e; //ok, e is an enumerator in base class B
+ * using B::x; //ok, x is an union member of base class B
+ * using C::g; //error, C isn't a base class of D
+ * }
+ */
+ public void testUsingDeclaration() throws Exception{
+ newTable();
+
+ Declaration B = new Declaration("B");
+ B.setType( Declaration.t_struct );
+ table.addDeclaration( B );
+ table.push( B );
+
+ Declaration f = new Declaration("f");
+ f.setType( Declaration.t_function );
+ table.addDeclaration( f );
+
+ Declaration E = new Declaration( "E" );
+ E.setType( Declaration.t_enumeration );
+ table.addDeclaration( E );
+
+ table.push( E );
+ Declaration e = new Declaration( "e" );
+ e.setType( Declaration.t_enumerator );
+ table.addDeclaration( e );
+ table.pop();
+
+ //TBD: Anonymous unions are not yet implemented
+
+ table.pop();
+
+ Declaration C = new Declaration( "C" );
+ C.setType( Declaration.t_class );
+ table.addDeclaration( C );
+
+ table.push( C );
+ Declaration g = new Declaration( "g" );
+ g.setType( Declaration.t_function );
+ table.addDeclaration( g );
+ table.pop();
+
+ Declaration D = new Declaration( "D" );
+ D.setType( Declaration.t_struct );
+ Declaration look = table.Lookup( "B" );
+ assertEquals( look, B );
+ D.addParent( look );
+
+ table.addDeclaration( D );
+ table.push( D );
+
+ Declaration lookB = table.LookupNestedNameSpecifier("B");
+ assertEquals( lookB, B );
+ table.push( lookB );
+ look = table.QualifiedLookup( "f" );
+ table.pop();
+
+ assertEquals( look, f );
+ table.addUsingDeclaration( look );
+
+ table.push( lookB );
+ look = table.QualifiedLookup( "e" );
+ table.pop();
+ assertEquals( look, e );
+ table.addUsingDeclaration( look );
+
+ //TBD anonymous union
+ //table.push( lookB );
+ //look = table.QualifiedLookup( "x")
+ //table.pop();
+ //table.addUsingDeclaration( look );
+
+ look = table.LookupNestedNameSpecifier("C");
+ assertEquals( look, C );
+ table.push( look );
+ look = table.QualifiedLookup("g");
+ table.pop();
+ assertEquals( look, g );
+
+ try{
+ table.addUsingDeclaration( look );
+ assertTrue( false );
+ }
+ catch ( ParserSymbolTableException exception ){
+ assertTrue( true );
+ }
+ }
+
+ /**
+ * testUsingDeclaration_2
+ * @throws Exception
+ * 7.3.3-9 The entity declared by a using-declaration shall be known in the
+ * context using it according to its definition at the point of the using-
+ * declaration. Definitions added to the namespace after the using-
+ * declaration are not considered when a use of the name is made.
+ *
+ * namespace A {
+ * void f(int);
+ * }
+ * using A::f;
+ *
+ * namespace A {
+ * void f(char);
+ * }
+ * void foo(){
+ * f('a'); //calls f( int )
+ * }
+ * void bar(){
+ * using A::f;
+ * f('a'); //calls f( char );
+ * }
+ *
+ * TBD: we need to support using declarations for overloaded functions.
+ * TBD: function overload resolution is not done yet, so the call to f in
+ * bar() can't be tested yet.
+ */
+ public void testUsingDeclaration_2() throws Exception{
+ newTable();
+
+ Declaration A = new Declaration( "A" );
+ A.setType( Declaration.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 );
+ table.addDeclaration( f1 );
+
+ table.pop();
+
+ Declaration look = table.LookupNestedNameSpecifier("A");
+ assertEquals( look, A );
+ table.push( A );
+ look = table.QualifiedLookup("f");
+ assertEquals( look, f1 );
+ table.pop();
+
+ Declaration usingF = table.addUsingDeclaration( look );
+
+ look = table.Lookup("A");
+ assertEquals( look, A );
+
+ table.push( look );
+ Declaration f2 = new Declaration("f");
+ f2.setType( Declaration.t_function );
+ f2.setReturnType( Declaration.t_void );
+ f2.addParameter( Declaration.t_char, "", false );
+
+ table.addDeclaration( f2 );
+
+ table.pop();
+
+ Declaration foo = new Declaration("foo");
+ foo.setType( Declaration.t_function );
+ table.addDeclaration( foo );
+ table.push( foo );
+ LinkedList paramList = new LinkedList();
+ Declaration.ParameterInfo param = foo.new ParameterInfo();
+ param.typeInfo = Declaration.t_char;
+ paramList.add( param );
+
+ look = table.UnqualifiedFunctionLookup( "f", paramList );
+ assertEquals( look, usingF );
+
+ }
+
+ /**
+ * testThisPointer
+ * @throws Exception
+ * In the body of a nonstatic member function... the type of this of a class
+ * X is X*. If the member function is declared const, the type of this is
+ * const X*, if the member function is declared volatile, the type of this
+ * is volatile X*....
+ */
+ public void testThisPointer() throws Exception{
+ newTable();
+
+ Declaration cls = new Declaration("class");
+ cls.setType( Declaration.t_class );
+
+ Declaration fn = new Declaration("function");
+ fn.setType( Declaration.t_function );
+ fn.setCVQualifier("const");
+
+ table.addDeclaration( cls );
+ table.push( cls );
+
+ table.addDeclaration( fn );
+ table.push( fn );
+
+ Declaration look = table.Lookup("this");
+ assertTrue( look != null );
+
+ assertEquals( look.getType(), Declaration.t_type );
+ assertEquals( look.getTypeDeclaration(), cls );
+ assertEquals( look.getPtrOperator(), "*" );
+ assertEquals( look.getCVQualifier(), fn.getCVQualifier() );
+ assertEquals( look.getContainingScope(), fn );
+ }
+
+ /**
+ * testEnumerator
+ * @throws Exception
+ * Following the closing brace of an enum-specifier, each enumerator has the
+ * type of its enumeration.
+ * The enum-name and each enumerator declared by an enum-specifier is
+ * declared in the scope that immediately contains the enum-specifier
+ */
+ public void testEnumerator() throws Exception{
+ newTable();
+
+ Declaration cls = new Declaration("class");
+ cls.setType( Declaration.t_class );
+
+ Declaration enumeration = new Declaration("enumeration");
+ enumeration.setType( Declaration.t_enumeration );
+
+ table.addDeclaration( cls );
+ table.push( cls );
+ table.addDeclaration( enumeration );
+ table.push( enumeration );
+
+ Declaration enumerator = new Declaration( "enumerator" );
+ enumerator.setType( Declaration.t_enumerator );
+ table.addDeclaration( enumerator );
+
+ table.pop();
+
+ Declaration look = table.Lookup( "enumerator" );
+ assertEquals( look, enumerator );
+ assertEquals( look.getContainingScope(), cls );
+ assertEquals( look.getTypeDeclaration(), enumeration );
+ }
+
+ /**
+ *
+ * @throws Exception
+ *
+ * namespace NS{
+ * class T {};
+ * void f( T );
+ * }
+ * NS::T parm;
+ * int main(){
+ * f( parm ); //ok, calls NS::f
+ * }
+ */
+ public void testArgumentDependentLookup() throws Exception{
+ newTable();
+
+ Declaration NS = new Declaration("NS");
+ NS.setType( Declaration.t_namespace );
+
+ table.addDeclaration( NS );
+ table.push( NS );
+
+ Declaration T = new Declaration("T");
+ T.setType( Declaration.t_class );
+
+ table.addDeclaration( T );
+
+ Declaration f = new Declaration("f");
+ f.setType( Declaration.t_function );
+ f.setReturnType( Declaration.t_void );
+
+ Declaration look = table.Lookup( "T" );
+ assertEquals( look, T );
+ f.addParameter( look, "", false );
+
+ table.addDeclaration( f );
+
+ table.pop(); //done NS
+
+ look = table.LookupNestedNameSpecifier( "NS" );
+ assertEquals( look, NS );
+ table.push( look );
+ look = table.QualifiedLookup( "T" );
+ assertEquals( look, T );
+ table.pop();
+
+ Declaration param = new Declaration("parm");
+ param.setType( Declaration.t_type );
+ param.setTypeDeclaration( look );
+ table.addDeclaration( param );
+
+ Declaration main = new Declaration("main");
+ main.setType( Declaration.t_function );
+ main.setReturnType( Declaration.t_int );
+ table.addDeclaration( main );
+ table.push( main );
+
+ LinkedList paramList = new LinkedList();
+ look = table.Lookup( "parm" );
+ assertEquals( look, param );
+
+ Declaration.ParameterInfo p = look.new ParameterInfo();
+ p.typeInfo = look.getType();
+ p.typeDeclaration = look.getTypeDeclaration();
+
+ paramList.add( p );
+
+ look = table.UnqualifiedFunctionLookup( "f", paramList );
+ assertEquals( look, f );
+ }
+
+ /**
+ * testArgumentDependentLookup_2
+ * @throws Exception
+ * in the following, NS2 is an associated namespace of class B which is an
+ * associated namespace of class A, so we should find f in NS2, we should
+ * not find f in NS1 because usings are ignored for associated scopes.
+ *
+ *
+ * namespace NS1{
+ * void f( void * ){};
+ * }
+ * namespace NS2{
+ * using namespace NS1;
+ * class B {};
+ * void f( void * ){};
+ * }
+ *
+ * class A : public NS2::B {};
+ *
+ * A a;
+ * f( &a );
+ *
+ */
+ public void testArgumentDependentLookup_2() throws Exception{
+ newTable();
+
+ Declaration NS1 = new Declaration( "NS1" );
+ NS1.setType( Declaration.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 );
+ table.addDeclaration( f1 );
+ table.pop();
+
+ Declaration NS2 = new Declaration( "NS2" );
+ NS2.setType( Declaration.t_namespace );
+
+ table.addDeclaration( NS2 );
+ table.push( NS2 );
+
+ Declaration look = table.Lookup( "NS1" );
+ assertEquals( look, NS1 );
+ table.addUsingDirective( look );
+
+ Declaration B = new Declaration( "B" );
+ B.setType( Declaration.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 );
+ table.addDeclaration( f2 );
+ table.pop();
+
+ Declaration A = new Declaration( "A" );
+ A.setType( Declaration.t_class );
+ look = table.LookupNestedNameSpecifier( "NS2" );
+ assertEquals( look, NS2 );
+ table.push( look );
+ look = table.QualifiedLookup( "B" );
+ assertEquals( look, B );
+ A.addParent( look );
+
+ table.addDeclaration( A );
+
+ look = table.Lookup( "A" );
+ assertEquals( look, A );
+ Declaration a = new Declaration( "a" );
+ a.setType( Declaration.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 );
+ paramList.add( param );
+
+ look = table.UnqualifiedFunctionLookup( "f", paramList );
+ assertEquals( look, f2 );
+ }
+
+ /**
+ * testFunctionOverloading
+ * @throws Exception
+ * Note that this test has been contrived to not strain the resolution as
+ * that aspect is not yet complete.
+ *
+ * class C
+ * {
+ * void foo( int i );
+ * void foo( int i, char c );
+ * void foo( int i, char c, C * ptr );
+ * }
+ *
+ * C * c = new C;
+ * c->foo( 1 );
+ * c->foo( 1, 'a' );
+ * c->foo( 1, 'a', c );
+ *
+ */
+
+ public void testFunctionOverloading() throws Exception{
+ newTable();
+
+ Declaration C = new Declaration( "C" );
+
+ table.addDeclaration(C);
+ table.push(C);
+
+ Declaration f1 = new Declaration("foo");
+ f1.setType( Declaration.t_function );
+ f1.setReturnType( Declaration.t_void );
+ f1.addParameter( Declaration.t_int, "", 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 );
+ 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 );
+ table.addDeclaration( f3 );
+ table.pop();
+
+ Declaration look = table.Lookup("C");
+ assertEquals( look, C );
+
+ Declaration c = new Declaration("c");
+ c.setType( Declaration.t_class );
+ c.setTypeDeclaration( look );
+ table.addDeclaration( c );
+
+ look = table.Lookup( "c" );
+ assertEquals( look, c );
+ assertEquals( look.getTypeDeclaration(), C );
+ 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);
+
+ paramList.add( p1 );
+ look = table.MemberFunctionLookup( "foo", paramList );
+ assertEquals( look, f1 );
+
+ paramList.add( p2 );
+ look = table.MemberFunctionLookup( "foo", paramList );
+ assertEquals( look, f2 );
+
+ paramList.add( p3 );
+ look = table.MemberFunctionLookup( "foo", paramList );
+ assertEquals( look, f3 );
+ }
}