Skip to content

Commit

Permalink
Fix for microsoft#191
Browse files Browse the repository at this point in the history
  • Loading branch information
SergeyTeplyakov committed Nov 7, 2015
1 parent c3085f5 commit 01b26c5
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 3 deletions.
39 changes: 38 additions & 1 deletion Foxtrot/Foxtrot/Utils/HelperMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2010,8 +2010,31 @@ internal static int MovePastClosureInit(Method m, Block firstBlock, ContractNode
return currentIndex;
}

if (closureCreationCandidate != null && closureCreationCandidate.SourceContext.IsValid)
// Following code was changed from simple check that closureCreationCandidate is not null and sourceContext is valid
// to method call IsBaseConstructorCall.
// Here is a history of this fix.
// Original code led to NullReferenceException for constructor with capturing lambda
// and field-like initializer compiled with VS2015.
//
// With VS2015 order of initialization was changed. Consider constructor initialization:
// VS2013:
// 1. Field-like initialization
// 2. Closure creation
// 3. Base class constructor call
// 4. Constructor body
// VS2015
// 1. Closure creation
// 2. Field-like initialization
// 3. Base class constructor call
// 4. Constructor body
//
// Previous version of the code worked incorrectly with VS2015 compiler.
// Because field-like initializer satisfy original criteria the function
// was unable to find closure initializer properly.
if (IsBaseContructorCall(closureCreationCandidate))
{
return currentIndex;
}

indexForClosureCreationStatement++;
}
Expand Down Expand Up @@ -2153,6 +2176,20 @@ internal static int MovePastClosureInit(Method m, Block firstBlock, ContractNode
return currentIndex;
}

private static bool IsBaseContructorCall(Statement statement)
{
var expression = statement as ExpressionStatement;
if (expression == null) return false;

var method = expression.Expression as MethodCall;
if (method == null) return false;

var callee = method.Callee as MemberBinding;
if (callee == null) return false;

return callee.BoundMember is InstanceInitializer;
}

private static bool IsDup(Statement statement)
{
var expr = statement as ExpressionStatement;
Expand Down
43 changes: 43 additions & 0 deletions Foxtrot/Tests/RewriterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1136,6 +1136,7 @@ private static IEnumerable<Options> RoslynCompatibilityData
{
get
{
// TODO: reduce code duplication by separating sequence of files from options.
yield return new Options(
sourceFile: @"Foxtrot\Tests\RoslynCompatibility\ConstructorWithCapturingLambda.cs",
foxtrotOptions: @"",
Expand All @@ -1157,6 +1158,48 @@ private static IEnumerable<Options> RoslynCompatibilityData
useBinDir: false,
useExe: true,
mustSucceed: true);
yield return new Options(
sourceFile: @"Foxtrot\Tests\RoslynCompatibility\ConstructorWithCapturingLambda2.cs",
foxtrotOptions: @"",
useContractReferenceAssemblies: true,
compilerOptions: @"",
references: new[] { @"System.Core.dll", @"System.Linq.Expressions.dll" },
libPaths: new[] { @"Microsoft.Research\RegressionTest\ClousotTestHarness\bin\debug" },
compilerCode: "CS",
useBinDir: false,
useExe: true,
mustSucceed: true);yield return new Options(
sourceFile: @"Foxtrot\Tests\RoslynCompatibility\ExpressionsInRequires.cs",
foxtrotOptions: @"",
useContractReferenceAssemblies: true,
compilerOptions: @"",
references: new[] { @"System.Core.dll", @"System.Linq.Expressions.dll" },
libPaths: new[] { @"Microsoft.Research\RegressionTest\ClousotTestHarness\bin\debug" },
compilerCode: "CS",
useBinDir: false,
useExe: true,
mustSucceed: true);
yield return new Options(
sourceFile: @"Foxtrot\Tests\RoslynCompatibility\ConstructorWithCapturingLambda3.cs",
foxtrotOptions: @"",
useContractReferenceAssemblies: true,
compilerOptions: @"",
references: new[] { @"System.Core.dll", @"System.Linq.Expressions.dll" },
libPaths: new[] { @"Microsoft.Research\RegressionTest\ClousotTestHarness\bin\debug" },
compilerCode: "CS",
useBinDir: false,
useExe: true,
mustSucceed: true);yield return new Options(
sourceFile: @"Foxtrot\Tests\RoslynCompatibility\ExpressionsInRequires.cs",
foxtrotOptions: @"",
useContractReferenceAssemblies: true,
compilerOptions: @"",
references: new[] { @"System.Core.dll", @"System.Linq.Expressions.dll" },
libPaths: new[] { @"Microsoft.Research\RegressionTest\ClousotTestHarness\bin\debug" },
compilerCode: "CS",
useBinDir: false,
useExe: true,
mustSucceed: true);
yield return new Options(
sourceFile: @"Foxtrot\Tests\RoslynCompatibility\AsyncWithLegacyRequires.cs",
foxtrotOptions: @"",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public sealed class CodeContractsCracker

public CodeContractsCracker(Action action)
{
Contract.Requires<ArgumentNullException>(action != null);
Contract.Requires(action != null);

this._actions.Add(() => action());
}
Expand All @@ -48,6 +48,6 @@ partial void Run()
}

public ContractFailureKind NegativeExpectedKind = ContractFailureKind.Precondition;
public string NegativeExpectedCondition = "Contract.Requires<ArgumentNullException>(action != null)";
public string NegativeExpectedCondition = "action != null";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// CodeContracts
//
// Copyright (c) Microsoft Corporation
//
// All rights reserved.
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

using System;
using System.Linq;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Text;
using System.Threading;

namespace Tests.Sources
{
public sealed class CodeContractsCracker
{
public CodeContractsCracker(string a)
{
Contract.Requires(a != null);

Delayed(() => Process(a));
}

private void Delayed(Action action)
{
}

private static void Process(string s)
{
}

public bool Flag = true;
}

partial class TestMain
{
partial void Run()
{
if (behave)
{
new CodeContractsCracker("foo");
}
else
{
new CodeContractsCracker(null);
}
}

public ContractFailureKind NegativeExpectedKind = ContractFailureKind.Precondition;
public string NegativeExpectedCondition = "a != null";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// CodeContracts
//
// Copyright (c) Microsoft Corporation
//
// All rights reserved.
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

using System;
using System.Linq;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Text;
using System.Threading;

namespace Tests.Sources
{
class A
{
object c = new object();

public A(object o)
{
Contract.Requires(o != null);

Action a = () => o.ToString();
}
}

partial class TestMain
{
partial void Run()
{
if (behave)
{
new A("foo");
}
else
{
new A(null);
}
}

public ContractFailureKind NegativeExpectedKind = ContractFailureKind.Precondition;
public string NegativeExpectedCondition = "o != null";
}
}

0 comments on commit 01b26c5

Please sign in to comment.