From 34877663fe55166c2ee165397811580f58c38f34 Mon Sep 17 00:00:00 2001 From: Doug Schaefer Date: Mon, 31 Mar 2003 20:43:07 +0000 Subject: [PATCH] Patch for Andrew Niefer: Core: (patch_03.31.03(cdt.core).txt) Modifications to function resolution to better support pointers, references and typedefs. Tests: (patch_03.31.03(cdt.ui.tests).txt) Renamed testFunctionResolution_2 to testfunctionResolution_PointersAndBaseClasses. Modified function tests to reflect changes made to the handling of parameters. Added testFunctionResolution_TypedefsAndPointers. --- core/org.eclipse.cdt.core/parser/ChangeLog | 4 + .../cdt/internal/core/parser/Declaration.java | 6 +- .../core/parser/ParserSymbolTable.java | 82 ++++++++-- .../internal/core/parser/util/TypeInfo.java | 153 ++++++++++++++++-- core/org.eclipse.cdt.ui.tests/ChangeLog | 5 + .../parser/tests/ParserSymbolTableTest.java | 113 ++++++++++++- 6 files changed, 323 insertions(+), 40 deletions(-) diff --git a/core/org.eclipse.cdt.core/parser/ChangeLog b/core/org.eclipse.cdt.core/parser/ChangeLog index 641584138fa..0ba23100129 100644 --- a/core/org.eclipse.cdt.core/parser/ChangeLog +++ b/core/org.eclipse.cdt.core/parser/ChangeLog @@ -1,3 +1,7 @@ +2003-03-31 Andrew Niefer + Parser Symbol Table, better support for function resolution with pointers and + references as parameters. Also support for typedefs as function parameters + 2003-03-31 John Camelon Updated Scanner to work for Strings literals like L"this string" Updated Scanner to work for floating points literals. 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 2eb9fbcf580..bb90fdf11d7 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 @@ -166,10 +166,10 @@ public class Declaration implements Cloneable { } public String getPtrOperator(){ - return _ptrOperator; + return _typeInfo.getPtrOperator(); } public void setPtrOperator( String ptrOp ){ - _ptrOperator = ptrOp; + _typeInfo.setPtrOperator( ptrOp ); } public int getReturnType(){ @@ -233,7 +233,7 @@ public class Declaration implements Cloneable { private Object _object; //the object associated with us private boolean _needsDefinition; //this name still needs to be defined private int _cvQualifier; - private String _ptrOperator; + //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) 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 0fd82d550f1..2c95139134b 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 @@ -760,19 +760,15 @@ public class ParserSymbolTable { data.visited.add( wrapper.parent ); } - //HashSet.add returns false if wrapper.parent is already in the set - //this means we have circular inheritance + //if the inheritanceChain already contains the parent, then that + //is circular inheritance if( ! data.inheritanceChain.contains( wrapper.parent ) ){ - //is this name define in this scope? temp = LookupInContained( data, wrapper.parent ); if( temp == null ){ temp = LookupInParents( data, wrapper.parent ); } - - //data.inheritanceChain.remove( wrapper.parent ); - } else { throw new ParserSymbolTableException( ParserSymbolTableException.r_CircularInheritance ); } @@ -799,7 +795,9 @@ public class ParserSymbolTable { temp = null; //reset temp for next iteration } } - data.inheritanceChain.remove( lookIn); + + data.inheritanceChain.remove( lookIn ); + return decl; } @@ -1270,7 +1268,7 @@ public class ParserSymbolTable { } } } - + /** * * @param source @@ -1290,7 +1288,7 @@ public class ParserSymbolTable { //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() ) + source.getType() == target.getType() ) { return 0; } @@ -1315,23 +1313,39 @@ public class ParserSymbolTable { * @return int * */ - static private int canConvert(TypeInfo source, TypeInfo target ){ + static private int canConvert(TypeInfo source, TypeInfo target ) throws ParserSymbolTableException{ int temp = 0; + source = getFlatTypeInfo( source ); + + String sourcePtr = source.getPtrOperator(); + String targetPtr = target.getPtrOperator(); + + if( sourcePtr != null && sourcePtr.equals("") ){ + sourcePtr = null; + } + if( targetPtr != null && targetPtr.equals("") ){ + targetPtr = null; + } + + boolean samePtrOp = ( ( sourcePtr == targetPtr ) || + ( sourcePtr != null && targetPtr != null && sourcePtr.equals( targetPtr ) ) ); //are they the same? if( source.getType() == target.getType() && - source.getTypeDeclaration() == target.getTypeDeclaration() ) + source.getTypeDeclaration() == target.getTypeDeclaration() && + samePtrOp ) { return 0; } //no go if they have different pointer qualification - if( ! source.getPtrOperator().equals( target.getPtrOperator() ) ){ + if( !samePtrOp ) + { return -1; } //TBD, do a better check on the kind of ptrOperator - if( !source.getPtrOperator().equals("*") ){ + if( sourcePtr == null || !sourcePtr.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 ) || @@ -1382,6 +1396,48 @@ public class ParserSymbolTable { (source.getCVQualifier() - source.getCVQualifier()) > 1 ); } + /** + * + * @param decl + * @return TypeInfo + * @throws ParserSymbolTableException + * The top level TypeInfo represents modifications to the object and the + * remaining TypeInfo's represent the object. + */ + static private TypeInfo getFlatTypeInfo( TypeInfo topInfo ) throws ParserSymbolTableException { + TypeInfo returnInfo = topInfo; + TypeInfo info = null; + + if( topInfo.getType() == TypeInfo.t_type ){ + returnInfo = new TypeInfo(); + + Declaration typeDecl = null; + + info = topInfo.getTypeDeclaration().getTypeInfo(); + + while( info.getType() == TypeInfo.t_type ){ + typeDecl = info.getTypeDeclaration(); + + returnInfo.addCVQualifier( info.getCVQualifier() ); + returnInfo.addPtrOperator( info.getPtrOperator() ); + + info = info.getTypeDeclaration().getTypeInfo(); + } + + returnInfo.setType( TypeInfo.t_type ); + returnInfo.setTypeDeclaration( typeDecl ); + + String ptrOp = returnInfo.getPtrOperator(); + returnInfo.setPtrOperator( topInfo.getInvertedPtrOperator() ); + + if( ptrOp != null ){ + returnInfo.addPtrOperator( ptrOp ); + } + } + + return returnInfo; + } + 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 index 0fe9b588529..30c4a72cb3d 100644 --- 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 @@ -39,10 +39,20 @@ public class TypeInfo{ _typeInfo = type; _typeDeclaration = decl; _cvQualifier = cvQualifier; - _ptrOperator = ptrOp; + _ptrOperator = ( ptrOp != null ) ? new String( ptrOp ) : null; _hasDefaultValue = hasDefault; } + + public TypeInfo( TypeInfo info ){ + super(); + _typeInfo = info._typeInfo; + _typeDeclaration = info._typeDeclaration; + _cvQualifier = info._cvQualifier; + _ptrOperator = ( info._ptrOperator == null ) ? null : new String( info._ptrOperator ); + _hasDefaultValue = info._hasDefaultValue; + } + public static final int typeMask = 0x001f; public static final int isAuto = 0x0020; public static final int isRegister = 0x0040; @@ -63,21 +73,22 @@ public class TypeInfo{ // 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; + public static final int t_undef = 0; //not specified + public static final int t_type = 1; // Type Specifier + public static final int t_namespace = 2; + public static final int t_class = 3; + public static final int t_struct = 4; + public static final int t_union = 5; + public static final int t_enumeration = 6; + public static final int t_function = 7; + public static final int t_bool = 8; + public static final int t_char = 9; + public static final int t_wchar_t = 10; + public static final int t_int = 11; + public static final int t_float = 12; + public static final int t_double = 13; + public static final int t_void = 14; + public static final int t_enumerator = 15; //Partial ordering : // none < const @@ -157,6 +168,29 @@ public class TypeInfo{ public void setCVQualifier( int cv ){ _cvQualifier = cv; } + + public void addCVQualifier( int cv ){ + switch( _cvQualifier ){ + case 0: + _cvQualifier = cv; + break; + + case cvConst: + if( cv != cvConst ){ + _cvQualifier = cvConstVolatile; + } + break; + + case cvVolatile: + if( cv != cvVolatile ){ + _cvQualifier = cvConstVolatile; + } + break; + + case cvConstVolatile: + break; //nothing to do + } + } public String getPtrOperator(){ return _ptrOperator; @@ -166,6 +200,93 @@ public class TypeInfo{ _ptrOperator = ptr; } + public void addPtrOperator( String ptr ){ + if( ptr == null ){ + return; + } + + char chars[] = ( _ptrOperator == null ) ? ptr.toCharArray() : ( ptr + _ptrOperator ).toCharArray(); + + int nChars = ( _ptrOperator == null ) ? ptr.length() : ptr.length() + _ptrOperator.length(); + + char dest[] = new char [ nChars ]; + int j = 0; + + char currChar, nextChar, tempChar; + + for( int i = 0; i < nChars; i++ ){ + currChar = chars[ i ]; + nextChar = ( i + 1 < nChars ) ? chars[ i + 1 ] : 0; + + switch( currChar ){ + case '&':{ + switch( nextChar ){ + case '[': + tempChar = ( i + 2 < nChars ) ? chars[ i + 2 ] : 0; + if( tempChar == ']' ){ + i++; + nextChar = '*'; + } + //fall through to '*' + case '*': + i++; + break; + case '&': + default: + dest[ j++ ] = currChar; + break; + } + break; + } + case '[':{ + if( nextChar == ']' ){ + i++; + currChar = '*'; + nextChar = ( i + 2 < nChars ) ? chars[ i + 2 ] : 0; + } + //fall through to '*' + } + case '*':{ + + if( nextChar == '&' ){ + i++; + } else { + dest[ j++ ] = currChar; + } + break; + } + default: + break; + + } + } + + _ptrOperator = new String( dest, 0, j ); + } + + public String getInvertedPtrOperator(){ + if( _ptrOperator == null ){ + return null; + } + + char chars[] = _ptrOperator.toCharArray(); + int nChars = _ptrOperator.length(); + + char dest[] = new char [ nChars ]; + char currChar; + + for( int i = 0; i < nChars; i++ ){ + currChar = chars[ i ]; + switch( currChar ){ + case '*' : dest[ i ] = '&'; break; + case '&' : dest[ i ] = '*'; break; + default: dest[ i ] = currChar; break; + } + } + + return new String( dest ); + } + public boolean getHasDefault(){ return _hasDefaultValue; } diff --git a/core/org.eclipse.cdt.ui.tests/ChangeLog b/core/org.eclipse.cdt.ui.tests/ChangeLog index 056958b7883..3e7d94f98f6 100644 --- a/core/org.eclipse.cdt.ui.tests/ChangeLog +++ b/core/org.eclipse.cdt.ui.tests/ChangeLog @@ -1,3 +1,8 @@ +2003-03-31 Andrew Niefer + In ParserSymbolTableTest, renamed testFunctionResolution_2() to testFunctionResolution_PointersAndBaseClasses(), + and modified to reflect changes in function resolution. + Added testFunctionResolution_TypedefsAndPointers(). + 2003-03-31 John Camelon Added testWeirdStrings() and testNumerics() to ScannerTestCase. Added testTemplateSpecialization(), testTemplateDeclaration(), testBug26467(), 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 a4df131ff5b..bc6d0239010 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 @@ -1508,7 +1508,7 @@ public class ParserSymbolTableTest extends TestCase { newTable(); Declaration C = new Declaration( "C" ); - + C.setType( TypeInfo.t_class ); table.addDeclaration(C); table.push(C); @@ -1538,8 +1538,9 @@ public class ParserSymbolTableTest extends TestCase { assertEquals( look, C ); Declaration c = new Declaration("c"); - c.setType( TypeInfo.t_class ); + c.setType( TypeInfo.t_type ); c.setTypeDeclaration( look ); + c.setPtrOperator( "*" ); table.addDeclaration( c ); look = table.Lookup( "c" ); @@ -1550,7 +1551,7 @@ public class ParserSymbolTableTest extends TestCase { LinkedList paramList = new LinkedList(); 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); + TypeInfo p3 = new TypeInfo( TypeInfo.t_type, c, 0, "", false); paramList.add( p1 ); look = table.MemberFunctionLookup( "foo", paramList ); @@ -1577,7 +1578,7 @@ public class ParserSymbolTableTest extends TestCase { * f( 'b' ); //calls f( char ); * f(); //calls f( char ); */ - public void testFunctionResolution_1() throws Exception{ + public void testFunctionResolution() throws Exception{ newTable(); Declaration f1 = new Declaration("f"); @@ -1613,7 +1614,7 @@ public class ParserSymbolTableTest extends TestCase { assertEquals( look, f2 ); } - /** + /** * * @throws Exception * @@ -1630,7 +1631,7 @@ public class ParserSymbolTableTest extends TestCase { * f( a ); //calls f( A * ); * f( c ); //calls f( B * ); */ - public void testFunctionResolution_2() throws Exception{ + public void testFunctionResolution_PointersAndBaseClasses() throws Exception{ newTable(); Declaration A = new Declaration( "A" ); @@ -1657,16 +1658,112 @@ public class ParserSymbolTableTest extends TestCase { f2.addParameter( B, 0, "*", false ); table.addDeclaration( f2 ); + Declaration a = new Declaration( "a" ); + a.setType( TypeInfo.t_type ); + a.setTypeDeclaration( A ); + a.setPtrOperator( "*" ); + + Declaration c = new Declaration( "c" ); + c.setType( TypeInfo.t_type ); + c.setTypeDeclaration( C ); + c.setPtrOperator( "*" ); + LinkedList paramList = new LinkedList(); - TypeInfo p1 = new TypeInfo( TypeInfo.t_type, A, 0, "*", false ); + TypeInfo p1 = new TypeInfo( TypeInfo.t_type, a, 0, null, 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 ); + TypeInfo p2 = new TypeInfo( TypeInfo.t_type, c, 0, "", false ); paramList.add( p2 ); look = table.UnqualifiedFunctionLookup( "f", paramList ); assertEquals( look, f2 ); } + + /** + * + * @throws Exception + * + * class A {}; + * typedef A * B; + * + * void f( A * ); + * void f( A ); + * + * A a; + * B b; + * A [] array; + * + * f( a ); //calls f( A ); + * f( &a ); //calls f( A * ); + * f( b ); //calls f( A * ); + * f( *b ); //calls f( A ); + * f( array ); //calls f( A * ); + */ + public void testFunctionResolution_TypedefsAndPointers() 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_type ); + B.setTypeDeclaration( A ); + B.setPtrOperator( "*" ); + table.addDeclaration( B ); + + 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( A, 0, null, false ); + table.addDeclaration( f2 ); + + Declaration a = new Declaration( "a" ); + a.setType( TypeInfo.t_type ); + a.setTypeDeclaration( A ); + table.addDeclaration( a ); + + Declaration b = new Declaration( "b" ); + b.setType( TypeInfo.t_type ); + b.setTypeDeclaration( B ); + table.addDeclaration( b ); + + Declaration array = new Declaration( "array" ); + array.setType( TypeInfo.t_type ); + array.setTypeDeclaration( A ); + array.setPtrOperator( "[]" ); + + LinkedList paramList = new LinkedList(); + TypeInfo p = new TypeInfo( TypeInfo.t_type, a, 0, null, false ); + paramList.add( p ); + + Declaration look = table.UnqualifiedFunctionLookup( "f", paramList ); + assertEquals( look, f2 ); + + p.setPtrOperator( "&" ); + look = table.UnqualifiedFunctionLookup( "f", paramList ); + assertEquals( look, f1 ); + + p.setTypeDeclaration( b ); + p.setPtrOperator( null ); + look = table.UnqualifiedFunctionLookup( "f", paramList ); + assertEquals( look, f1 ); + + p.setPtrOperator( "*" ); + look = table.UnqualifiedFunctionLookup( "f", paramList ); + assertEquals( look, f2 ); + + p.setTypeDeclaration( array ); + p.setPtrOperator( null ); + look = table.UnqualifiedFunctionLookup( "f", paramList ); + assertEquals( look, f1 ); + + } } +