diff --git a/src/Build.UnitTests/Evaluation/Expander_Tests.cs b/src/Build.UnitTests/Evaluation/Expander_Tests.cs
index 3b04989a30b..b55b0dec344 100644
--- a/src/Build.UnitTests/Evaluation/Expander_Tests.cs
+++ b/src/Build.UnitTests/Evaluation/Expander_Tests.cs
@@ -3400,22 +3400,25 @@ public void PropertyFunctionStaticMethodIntrinsicMaths()
double expectedResult = 9223372036854775807D + 20D;
Assert.Equal(expectedResult.ToString(), result);
+ }
- result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::BitwiseOr(40, 2))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
-
- Assert.Equal((40 | 2).ToString(), result);
-
- result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::BitwiseAnd(42, 2))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
-
- Assert.Equal((42 & 2).ToString(), result);
-
- result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::BitwiseXor(213, 255))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
-
- Assert.Equal((213 ^ 255).ToString(), result);
+ ///
+ /// Expand intrinsic property functions that call a bit operator
+ ///
+ [Fact]
+ public void PropertyFunctionStaticMethodIntrinsicBitOperations()
+ {
+ PropertyDictionary pg = new PropertyDictionary();
- result = expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::BitwiseNot(-43))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
+ Expander expander = new Expander(pg, FileSystems.Default);
- Assert.Equal((~-43).ToString(), result);
+ expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::BitwiseOr(40, 2))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance).ShouldBe((40 | 2).ToString());
+ expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::BitwiseAnd(42, 2))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance).ShouldBe((42 & 2).ToString());
+ expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::BitwiseXor(213, 255))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance).ShouldBe((213 ^ 255).ToString());
+ expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::BitwiseNot(-43))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance).ShouldBe((~-43).ToString());
+ expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::LeftShift(1, 2))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance).ShouldBe((1 << 2).ToString());
+ expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::RightShift(-8, 2))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance).ShouldBe((-8 >> 2).ToString());
+ expander.ExpandIntoStringLeaveEscaped(@"$([MSBuild]::RightShiftUnsigned(-8, 2))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance).ShouldBe((-8 >>> 2).ToString());
}
///
diff --git a/src/Build/Evaluation/Expander.cs b/src/Build/Evaluation/Expander.cs
index c76c6a47780..1478cc17550 100644
--- a/src/Build/Evaluation/Expander.cs
+++ b/src/Build/Evaluation/Expander.cs
@@ -3887,6 +3887,14 @@ private bool TryExecuteWellKnownFunction(out object returnVal, object objectInst
return true;
}
}
+ else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.Unescape), StringComparison.OrdinalIgnoreCase))
+ {
+ if (TryGetArg(args, out string arg0))
+ {
+ returnVal = IntrinsicFunctions.Unescape(arg0);
+ return true;
+ }
+ }
else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.GetPathOfFileAbove), StringComparison.OrdinalIgnoreCase))
{
if (TryGetArgs(args, out string arg0, out string arg1))
@@ -3899,7 +3907,7 @@ private bool TryExecuteWellKnownFunction(out object returnVal, object objectInst
{
if (TryGetArgs(args, out double arg0, out double arg1))
{
- returnVal = arg0 + arg1;
+ returnVal = IntrinsicFunctions.Add(arg0, arg1);
return true;
}
}
@@ -3907,7 +3915,7 @@ private bool TryExecuteWellKnownFunction(out object returnVal, object objectInst
{
if (TryGetArgs(args, out double arg0, out double arg1))
{
- returnVal = arg0 - arg1;
+ returnVal = IntrinsicFunctions.Subtract(arg0, arg1);
return true;
}
}
@@ -3915,7 +3923,7 @@ private bool TryExecuteWellKnownFunction(out object returnVal, object objectInst
{
if (TryGetArgs(args, out double arg0, out double arg1))
{
- returnVal = arg0 * arg1;
+ returnVal = IntrinsicFunctions.Multiply(arg0, arg1);
return true;
}
}
@@ -3923,7 +3931,15 @@ private bool TryExecuteWellKnownFunction(out object returnVal, object objectInst
{
if (TryGetArgs(args, out double arg0, out double arg1))
{
- returnVal = arg0 / arg1;
+ returnVal = IntrinsicFunctions.Divide(arg0, arg1);
+ return true;
+ }
+ }
+ else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.Modulo), StringComparison.OrdinalIgnoreCase))
+ {
+ if (TryGetArgs(args, out double arg0, out double arg1))
+ {
+ returnVal = IntrinsicFunctions.Modulo(arg0, arg1);
return true;
}
}
@@ -4113,6 +4129,62 @@ private bool TryExecuteWellKnownFunction(out object returnVal, object objectInst
return true;
}
}
+ else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.BitwiseOr), StringComparison.OrdinalIgnoreCase))
+ {
+ if (TryGetArgs(args, out int arg0, out int arg1))
+ {
+ returnVal = IntrinsicFunctions.BitwiseOr(arg0, arg1);
+ return true;
+ }
+ }
+ else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.BitwiseAnd), StringComparison.OrdinalIgnoreCase))
+ {
+ if (TryGetArgs(args, out int arg0, out int arg1))
+ {
+ returnVal = IntrinsicFunctions.BitwiseAnd(arg0, arg1);
+ return true;
+ }
+ }
+ else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.BitwiseXor), StringComparison.OrdinalIgnoreCase))
+ {
+ if (TryGetArgs(args, out int arg0, out int arg1))
+ {
+ returnVal = IntrinsicFunctions.BitwiseXor(arg0, arg1);
+ return true;
+ }
+ }
+ else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.BitwiseNot), StringComparison.OrdinalIgnoreCase))
+ {
+ if (TryGetArgs(args, out int arg0))
+ {
+ returnVal = IntrinsicFunctions.BitwiseNot(arg0);
+ return true;
+ }
+ }
+ else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.LeftShift), StringComparison.OrdinalIgnoreCase))
+ {
+ if (TryGetArgs(args, out int arg0, out int arg1))
+ {
+ returnVal = IntrinsicFunctions.LeftShift(arg0, arg1);
+ return true;
+ }
+ }
+ else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.RightShift), StringComparison.OrdinalIgnoreCase))
+ {
+ if (TryGetArgs(args, out int arg0, out int arg1))
+ {
+ returnVal = IntrinsicFunctions.RightShift(arg0, arg1);
+ return true;
+ }
+ }
+ else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.RightShiftUnsigned), StringComparison.OrdinalIgnoreCase))
+ {
+ if (TryGetArgs(args, out int arg0, out int arg1))
+ {
+ returnVal = IntrinsicFunctions.RightShiftUnsigned(arg0, arg1);
+ return true;
+ }
+ }
}
else if (_receiverType == typeof(Path))
{
@@ -4489,6 +4561,18 @@ private static bool TryGetArgs(object[] args, out string arg0, out StringCompari
return Enum.TryParse(comparisonTypeName, out arg1);
}
+ private static bool TryGetArgs(object[] args, out int arg0)
+ {
+ arg0 = 0;
+
+ if (args.Length != 1)
+ {
+ return false;
+ }
+
+ return TryConvertToInt(args[0], out arg0);
+ }
+
private static bool TryGetArgs(object[] args, out int arg0, out int arg1)
{
arg0 = 0;
diff --git a/src/Build/Evaluation/IntrinsicFunctions.cs b/src/Build/Evaluation/IntrinsicFunctions.cs
index 45ebc5e9a0c..3fff5c28e65 100644
--- a/src/Build/Evaluation/IntrinsicFunctions.cs
+++ b/src/Build/Evaluation/IntrinsicFunctions.cs
@@ -165,6 +165,21 @@ internal static int BitwiseNot(int first)
return ~first;
}
+ internal static int LeftShift(int operand, int count)
+ {
+ return operand << count;
+ }
+
+ internal static int RightShift(int operand, int count)
+ {
+ return operand >> count;
+ }
+
+ internal static int RightShiftUnsigned(int operand, int count)
+ {
+ return operand >>> count;
+ }
+
///
/// Get the value of the registry key and value, default value is null
///