diff --git a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.NodeMapBuilder.cs b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.NodeMapBuilder.cs
index 4d71ba03c7188..f6d1866180c4d 100644
--- a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.NodeMapBuilder.cs
+++ b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.NodeMapBuilder.cs
@@ -223,13 +223,8 @@ public override BoundNode Visit(BoundNode node)
/// The bound node.
private bool ShouldAddNode(BoundNode currentBoundNode)
{
- BoundBlock block;
-
// Do not add compiler generated nodes.
- if (currentBoundNode.WasCompilerGenerated &&
- (currentBoundNode.Kind != BoundKind.Block ||
- (block = (BoundBlock)currentBoundNode).Statements.Length != 1 ||
- block.Statements.Single().WasCompilerGenerated))
+ if (currentBoundNode.WasCompilerGenerated)
{
return false;
}
diff --git a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs
index e00dc3d234dca..e4e42d2129977 100644
--- a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs
+++ b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs
@@ -26,6 +26,7 @@ internal abstract partial class MemberSemanticModel : CSharpSemanticModel
private readonly ReaderWriterLockSlim _nodeMapLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
// The bound nodes associated with a syntax node, from highest in the tree to lowest.
private readonly Dictionary> _guardedNodeMap = new Dictionary>();
+ private Dictionary _lazyGuardedSynthesizedStatementsMap;
internal readonly Binder RootBinder;
@@ -1184,6 +1185,27 @@ private CSharpSyntaxNode GetInnermostLambdaOrQuery(CSharpSyntaxNode node, int po
return null;
}
+ private void GuardedAddSynthesizedStatementToMap(StatementSyntax node, BoundStatement statement)
+ {
+ if (_lazyGuardedSynthesizedStatementsMap == null)
+ {
+ _lazyGuardedSynthesizedStatementsMap = new Dictionary();
+ }
+
+ _lazyGuardedSynthesizedStatementsMap.Add(node, statement);
+ }
+
+ private BoundStatement GuardedGetSynthesizedStatementFromMap(StatementSyntax node)
+ {
+ if (_lazyGuardedSynthesizedStatementsMap != null &&
+ _lazyGuardedSynthesizedStatementsMap.TryGetValue(node, out BoundStatement result))
+ {
+ return result;
+ }
+
+ return null;
+ }
+
private ImmutableArray GuardedGetBoundNodesFromMap(CSharpSyntaxNode node)
{
Debug.Assert(_nodeMapLock.IsWriteLockHeld || _nodeMapLock.IsReadLockHeld);
@@ -1896,12 +1918,28 @@ internal override Binder GetBinder(SyntaxNode node)
public override BoundStatement BindStatement(StatementSyntax node, DiagnosticBag diagnostics)
{
// Check the bound node cache to see if the statement was already bound.
+ BoundStatement synthesizedStatement = _semanticModel.GuardedGetSynthesizedStatementFromMap(node);
+
+ if (synthesizedStatement != null)
+ {
+ return synthesizedStatement;
+ }
+
ImmutableArray boundNodes = _semanticModel.GuardedGetBoundNodesFromMap(node);
if (boundNodes.IsDefaultOrEmpty)
{
// Not bound already. Bind it. It will get added to the cache later by a MemberSemanticModel.NodeMapBuilder.
- return base.BindStatement(node, diagnostics);
+ var statement = base.BindStatement(node, diagnostics);
+
+ // Synthesized statements are not added to the _guardedNodeMap, we cache them explicitly here in
+ // _lazyGuardedSynthesizedStatementsMap
+ if (statement.WasCompilerGenerated)
+ {
+ _semanticModel.GuardedAddSynthesizedStatementToMap(node, statement);
+ }
+
+ return statement;
}
else
{
diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/OutVarTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/OutVarTests.cs
index de4052622dbd8..516846814c3f8 100644
--- a/src/Compilers/CSharp/Test/Semantic/Semantics/OutVarTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Semantics/OutVarTests.cs
@@ -32882,6 +32882,36 @@ static void G(out object o)
var info = model.GetSymbolInfo(identifierAfter);
Assert.Equal("void C.G(out System.Object o)", info.Symbol.ToTestDisplayString());
}
+
+ [Fact]
+ [WorkItem(10604, "https://github.com/dotnet/roslyn/issues/10604")]
+ [WorkItem(16306, "https://github.com/dotnet/roslyn/issues/16306")]
+ public void GetForEachSymbolInfoWithOutVar()
+ {
+ var source =
+@"using System.Collections.Generic;
+public class C
+{
+ void M()
+ {
+ foreach (var x in M2(out int i)) { }
+ }
+ IEnumerable