瀏覽代碼

Test and coerce const arg types in function calls.
Fixes issue where a constant arg would fail widen test, even though the arg value was within the valid range of the function param.

woollybah 9 年之前
父節點
當前提交
bbd86432a2
共有 2 個文件被更改,包括 75 次插入7 次删除
  1. 9 7
      decl.bmx
  2. 66 0
      expr.bmx

+ 9 - 7
decl.bmx

@@ -1183,22 +1183,24 @@ End Rem
 	
 					If i<argExprs.Length And argExprs[i]
 					
+						Local arg:TExpr = argExprs[i]
+					
 						Local declTy:TType=argDecls[i].ty
-						Local exprTy:TType=argExprs[i].exprType
+						Local exprTy:TType=arg.exprType
 						
 						Local widensTest:Int = True
 						
 						' for numeric constants, allow them to be auto-cast unless
-						'If TConstExpr(argExprs[i]) And TNumericType(exprTy) And Not TConstExpr(argExprs[i]).typeSpecific Then
-						'	widensTest = False
-						'End If
+						If TConstExpr(arg) And IsNumericType(exprTy) And Not TConstExpr(arg).typeSpecific And TConstExpr(arg).CompatibleWithType(declTy) Then
+							widensTest = False
+						End If
 	
-						If TFunctionPtrType(declTy) And TInvokeExpr(argExprs[i]) Then
-							If TFunctionPtrType(declTy).equalsDecl(TInvokeExpr(argExprs[i]).decl) Continue
+						If TFunctionPtrType(declTy) And TInvokeExpr(arg) Then
+							If TFunctionPtrType(declTy).equalsDecl(TInvokeExpr(arg).decl) Continue
 						End If
 	
 						' not ideal - since the arg is configured as a Byte Ptr, we can't check that the function is of the correct type.
-						If IsPointerType(declTy, TType.T_BYTE) And TInvokeExpr(argExprs[i]) And TInvokeExpr(argExprs[i]).invokedWithBraces = 0 Then
+						If IsPointerType(declTy, TType.T_BYTE) And TInvokeExpr(arg) And TInvokeExpr(arg).invokedWithBraces = 0 Then
 							Continue
 						End If
 						

+ 66 - 0
expr.bmx

@@ -348,6 +348,7 @@ Type TConstExpr Extends TExpr
 	Field ty:TType
 	Field value$
 	Field originalValue$
+	' True if the const was identified as a specific type.
 	Field typeSpecific:Int
 
 	Method Create:TConstExpr( ty:TType,value$ )
@@ -459,6 +460,71 @@ Type TConstExpr Extends TExpr
 		End If
 		Return New TCastExpr.Create( ty,expr,castFlags ).Semant()
 	End Method
+	
+	Method CompatibleWithType:Int(ty:TType)
+		If Not TDecimalType(ty) Then
+			If value.Contains("e") Or value.Contains("E") Or value.Contains(".") Or value.Contains("inf") Or value.Contains("nan") Then
+				Return False
+			End If
+			
+			Local val:Long = value.ToLong()
+			
+			If val < 0 Then
+				If TByteType(ty) Or TShortType(ty) Or TUIntType(ty) Or TULongType(ty) Or TSizeTType(ty) Then
+					Return False
+				End If
+			Else
+				If TByteType(ty) Then
+					If value <> String.FromInt(Byte(Val)) Then
+						Return False
+					End If
+				End If
+
+				If TUIntType(ty) Or (TSizeTType(ty) And WORD_SIZE = 4) Then
+					If val > 4294967296:Long Then
+						Return False
+					End If
+				End If
+				
+				If TULongType(ty) Or (TSizeTType(ty) And WORD_SIZE = 8) Then
+					If value.length > 20 Then
+						Return False
+					Else If value.length = 20 Then
+						For Local i:Int = 0 Until value.length
+							Local v:Int = value[i]
+							Local n:Int = "18446744073709551616"[i]
+							If v < n Then
+								Exit 
+							Else If v > n Then
+								Return False
+							End If
+						Next
+					End If
+				End If
+			End If
+			
+			If TShortType(ty) Then
+				If value <> String.FromInt(Short(val)) Then
+					Return False
+				End If
+			End If
+
+			If TIntType(ty) Then
+				If value <> String.FromInt(Int(val)) Then
+					Return False
+				End If
+			End If
+
+			If TLongType(ty) Then
+				If value <> String.FromLong(Long(val)) Then
+					Return False
+				End If
+			End If
+			
+		End If
+		
+		Return True
+	End Method
 
 End Type