Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
[cdt-patch] Parser Symbol Table

(I meant to send this yesterday)

- Fix some NPEs in the parser Symbol table.
- add some comments and constants to help clarify ranking of conversion 
sequences

-Andrew

Index: parser/ChangeLog
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/parser/ChangeLog,v
retrieving revision 1.118
diff -u -r1.118 ChangeLog
--- parser/ChangeLog	9 Sep 2003 18:02:40 -0000	1.118
+++ parser/ChangeLog	9 Sep 2003 19:22:05 -0000
@@ -1,3 +1,7 @@
+2003-09-09 Andrew Niefer
+	Fixed some NPEs in ParserSymbolTable.getFlatTypeInfo
+	Added some comments and created some constants to help clarify ranking of conversion sequences
+
 2003-09-09 John Camelon
 	Updated ScannerException to be more precise and include more information.  
 	Updated Parser to be more careful of how it handles particular Scanner errors in COMPLETE_PARSE mode.  
Index: parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTable.java
===================================================================
RCS file: /home/tools/org.eclipse.cdt.core/parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTable.java,v
retrieving revision 1.17
diff -u -r1.17 ParserSymbolTable.java
--- parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTable.java	8 Sep 2003 18:10:49 -0000	1.17
+++ parser/org/eclipse/cdt/internal/core/parser/pst/ParserSymbolTable.java	9 Sep 2003 19:22:06 -0000
@@ -738,13 +738,13 @@
 				target = ((ISymbol)targetParams.next()).getTypeInfo();
 				if( source.equals( target ) ){
 					cost = new Cost( source, target );
-					cost.rank = 0;	//exact match, no cost
+					cost.rank = Cost.IDENTITY_RANK;	//exact match, no cost
 				} else {
 					cost = checkStandardConversionSequence( source, target );
 					
 					//12.3-4 At most one user-defined conversion is implicitly applied to
 					//a single value.  (also prevents infinite loop)				
-					if( cost.rank == -1 && !data.forUserDefinedConversion ){
+					if( cost.rank == Cost.NO_MATCH_RANK && !data.forUserDefinedConversion ){
 						temp = checkUserDefinedConversionSequence( source, target );
 						if( temp != null ){
 							cost = temp;
@@ -758,7 +758,9 @@
 			
 			hasWorse = false;
 			hasBetter = false;
-			
+			//In order for this function to be better than the previous best, it must
+			//have at least one parameter match that is better that the corresponding
+			//match for the other function, and none that are worse.
 			for( int j = 0; j < numParams; j++ ){ 
 				if( currFnCost[ j ].rank < 0 ){
 					hasWorse = true;
@@ -766,6 +768,8 @@
 					break;
 				}
 				
+				//an ambiguity in the user defined conversion sequence is only a problem
+				//if this function turns out to be the best.
 				currHasAmbiguousParam = ( currFnCost[ j ].userDefined == 1 );
 				
 				if( bestFnCost != null ){
@@ -776,11 +780,15 @@
 					hasBetter = true;
 				}
 			}
-				
+			
+			//If function has a parameter match that is better than the current best,
+			//and another that is worse (or everything was just as good, neither better nor worse).
+			//then this is an ambiguity (unless we find something better than both later)	
 			ambiguous |= ( hasWorse && hasBetter ) || ( !hasWorse && !hasBetter );
 			
 			if( !hasWorse ){
 				if( hasBetter ){
+					//the new best function.
 					ambiguous = false;
 					bestFnCost = currFnCost;
 					bestHasAmbiguousParam = currHasAmbiguousParam;
@@ -1091,6 +1099,13 @@
 		}
 		
 		Cost cost = new Cost( source, target );
+		
+		//if either source or target is null here, then there was a problem 
+		//with the parameters and we can't match them.
+		if( cost.source == null || cost.target == null ){
+			return cost;
+		}
+		
 		TypeInfo.PtrOp op = null;
 		
 		if( cost.source.hasPtrOperators() ){
@@ -1132,6 +1147,12 @@
 		return cost;
 	}
 	
+	/**
+	 * qualificationConversion
+	 * @param cost
+	 * 
+	 * see spec section 4.4 regarding qualification conversions
+	 */
 	static private void qualificationConversion( Cost cost ){
 		int size = cost.source.hasPtrOperators() ? cost.source.getPtrOperators().size() : 0;
 		int size2 = cost.target.hasPtrOperators() ? cost.target.getPtrOperators().size() : 0;
@@ -1149,6 +1170,7 @@
 			op1 = (TypeInfo.PtrOp) iter1.next();
 			op2 = (TypeInfo.PtrOp) iter2.next();
 			
+			//can only convert if op2 is more qualified
 			if( ( op1.isConst()    && !op2.isConst() ) ||
 				( op1.isVolatile() && !op2.isVolatile() ) )
 			{
@@ -1166,7 +1188,7 @@
 				op1 = (TypeInfo.PtrOp) iter1.next();
 				op2 = (TypeInfo.PtrOp) iter2.next();
 				
-				//pointer types are similar
+				//pointer types must be similar
 				if( op1.getType() != op2.getType() ){
 					canConvert = false;
 					break;
@@ -1191,7 +1213,7 @@
 		
 		if( canConvert == true ){
 			cost.qualification = 1;
-			cost.rank = 0;
+			cost.rank = Cost.LVALUE_OR_QUALIFICATION_RANK;
 		} else {
 			cost.qualification = 0;
 		}
@@ -1235,7 +1257,7 @@
 			cost.promotion = 0;
 		}
 		
-		cost.rank = (cost.promotion > 0 ) ? 1 : -1;
+		cost.rank = (cost.promotion > 0 ) ? Cost.PROMOTION_RANK : Cost.NO_MATCH_RANK;
 	}
 	
 	/**
@@ -1269,7 +1291,7 @@
 				//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( trg.isType( TypeInfo.t_void ) ){
-					cost.rank = 2;
+					cost.rank = Cost.CONVERSION_RANK;
 					cost.conversion = 1;
 					cost.detail = 2;
 					return;	
@@ -1281,7 +1303,7 @@
 				// to an rvalue of type "pointer to cv B", where B is a base class of D.
 				if( (srcDecl instanceof IDerivableContainerSymbol) && trgDecl.isType( srcDecl.getType() ) ){
 					temp = hasBaseClass( (IDerivableContainerSymbol) srcDecl, (IDerivableContainerSymbol) trgDecl );
-					cost.rank = 2;
+					cost.rank = Cost.CONVERSION_RANK;
 					cost.conversion = ( temp > -1 ) ? temp : 0;
 					cost.detail = 1;
 					return;
@@ -1297,7 +1319,7 @@
 				TypeInfo.PtrOp srcPtr =  trg.hasPtrOperators() ? (TypeInfo.PtrOp)trg.getPtrOperators().getFirst() : null;
 				if( trgDecl.isType( srcDecl.getType() ) && srcPtr != null && srcPtr.getType() == TypeInfo.PtrOp.t_memberPointer ){
 					temp = hasBaseClass( (IDerivableContainerSymbol)ptr.getMemberOf(), (IDerivableContainerSymbol)srcPtr.getMemberOf() );
-					cost.rank = 2;
+					cost.rank = Cost.CONVERSION_RANK;
 					cost.detail = 1;
 					cost.conversion = ( temp > -1 ) ? temp : 0;
 					return; 
@@ -1313,7 +1335,7 @@
 				if( trg.isType( TypeInfo.t_bool, TypeInfo.t_int ) ||
 					trg.isType( TypeInfo.t_float, TypeInfo.t_double ) )
 				{
-					cost.rank = 2;
+					cost.rank = Cost.CONVERSION_RANK;
 					cost.conversion = 1;	
 				}
 			}
@@ -1323,8 +1345,12 @@
 	static private Cost checkStandardConversionSequence( TypeInfo source, TypeInfo target ){
 		Cost cost = lvalue_to_rvalue( source, target );
 		
+		if( cost.source == null || cost.target == null ){
+			return cost;
+		}
+			
 		if( cost.source.equals( cost.target ) ){
-			cost.rank = 0;
+			cost.rank = Cost.IDENTITY_RANK;
 			return cost;
 		}
 	
@@ -1384,7 +1410,7 @@
 		//conversion operators
 		if( source.getType() == TypeInfo.t_type ){
 			source = getFlatTypeInfo( source );
-			sourceDecl = source.getTypeSymbol();
+			sourceDecl = ( source != null ) ? source.getTypeSymbol() : null;
 			
 			if( sourceDecl != null && (sourceDecl instanceof IContainerSymbol) ){
 				String name = target.toString();
@@ -1409,21 +1435,21 @@
 		}
 		
 		//if both are valid, then the conversion is ambiguous
-		if( constructorCost != null && constructorCost.rank != -1 && 
-			conversionCost != null && conversionCost.rank != -1 )
+		if( constructorCost != null && constructorCost.rank != Cost.NO_MATCH_RANK && 
+			conversionCost != null && conversionCost.rank != Cost.NO_MATCH_RANK )
 		{
 			cost = constructorCost;
-			cost.userDefined = 1;
-			cost.rank = 3;
+			cost.userDefined = Cost.AMBIGUOUS_USERDEFINED_CONVERSION;	
+			cost.rank = Cost.USERDEFINED_CONVERSION_RANK;
 		} else {
-			if( constructorCost != null && constructorCost.rank != -1 ){
+			if( constructorCost != null && constructorCost.rank != Cost.NO_MATCH_RANK ){
 				cost = constructorCost;
 				cost.userDefined = constructor.hashCode();
-				cost.rank = 3;
-			} else if( conversionCost != null && conversionCost.rank != -1 ){
+				cost.rank = Cost.USERDEFINED_CONVERSION_RANK;
+			} else if( conversionCost != null && conversionCost.rank != Cost.NO_MATCH_RANK ){
 				cost = conversionCost;
 				cost.userDefined = conversion.hashCode();
-				cost.rank = 3;
+				cost.rank = Cost.USERDEFINED_CONVERSION_RANK;
 			} 			
 		}
 		
@@ -1442,12 +1468,12 @@
 		TypeInfo returnInfo = topInfo;
 		TypeInfo info = null;
 		
-		if( topInfo.getType() == TypeInfo.t_type ){
+		if( topInfo.getType() == TypeInfo.t_type && topInfo.getTypeSymbol() != null ){
 			returnInfo = (TypeInfo)new TypeInfo();
 			
 			ISymbol typeSymbol = topInfo.getTypeSymbol();
 			
-			info = topInfo.getTypeSymbol().getTypeInfo();
+			info = typeSymbol.getTypeInfo();
 			
 			while( info.getType() == TypeInfo.t_type || ( info.isForwardDeclaration() && info.getTypeSymbol() != null ) ){
 				typeSymbol = info.getTypeSymbol();
@@ -2038,6 +2064,16 @@
 		public int rank = -1;
 		public int detail;
 		
+		//Some constants to help clarify things
+		public static final int AMBIGUOUS_USERDEFINED_CONVERSION = 1;
+		
+		public static final int NO_MATCH_RANK = -1;
+		public static final int IDENTITY_RANK = 0;
+		public static final int LVALUE_OR_QUALIFICATION_RANK = 0;
+		public static final int PROMOTION_RANK = 1;
+		public static final int CONVERSION_RANK = 2;
+		public static final int USERDEFINED_CONVERSION_RANK = 3;
+		
 		public int compare( Cost cost ){
 			int result = 0;
 			
@@ -2049,7 +2085,7 @@
 				if( userDefined == 0 || cost.userDefined == 0 ){
 					return cost.userDefined - userDefined;
 				} else {
-					if( (userDefined == 1 || cost.userDefined == 1) ||
+					if( (userDefined == AMBIGUOUS_USERDEFINED_CONVERSION || cost.userDefined == AMBIGUOUS_USERDEFINED_CONVERSION) ||
 						(userDefined != cost.userDefined ) )
 					{
 						return 0;
@@ -3132,6 +3168,10 @@
 				param = (TypeInfo) iter.next();
 				paramType = ParserSymbolTable.getFlatTypeInfo( param ).getTypeSymbol();
 			
+				if( paramType == null ){
+					continue;
+				}
+					
 				ParserSymbolTable.getAssociatedScopes( paramType, associated );
 			
 				//if T is a pointer to a data member of class X, its associated namespaces and classes

Back to the top