Skip to content

Commit 1a155b3

Browse files
authored
Merge pull request github#15667 from michaelnebel/csharp/syntheticconstructorbody
C#: Add synthetic bodies and inititializers for default constuctors.
2 parents 9411352 + a24a57c commit 1a155b3

File tree

23 files changed

+1611
-29
lines changed

23 files changed

+1611
-29
lines changed

csharp/extractor/Semmle.Extraction.CSharp/Entities/Constructor.cs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ public override void Populate(TextWriter trapFile)
3232
trapFile.constructors(this, Symbol.ContainingType.Name, ContainingType, (Constructor)OriginalDefinition);
3333
trapFile.constructor_location(this, Location);
3434

35-
if (IsPrimary)
35+
if (MakeSynthetic)
3636
{
37-
// Create a synthetic empty body for primary constructors.
37+
// Create a synthetic empty body for primary and default constructors.
3838
Statements.SyntheticEmptyBlock.Create(Context, this, 0, Location);
3939
}
4040

@@ -49,9 +49,9 @@ public override void Populate(TextWriter trapFile)
4949
protected override void ExtractInitializers(TextWriter trapFile)
5050
{
5151
// Do not extract initializers for constructed types.
52-
// Only extract initializers for constructors with a body and primary constructors.
53-
if (Block is null && ExpressionBody is null && !IsPrimary ||
54-
!IsSourceDeclaration)
52+
// Extract initializers for constructors with a body, primary constructors
53+
// and default constructors for classes and structs declared in source code.
54+
if (Block is null && ExpressionBody is null && !MakeSynthetic)
5555
{
5656
return;
5757
}
@@ -161,6 +161,16 @@ private void ExtractSourceInitializer(TextWriter trapFile, ITypeSymbol? type, IM
161161

162162
private bool IsPrimary => PrimaryConstructorSyntax is not null;
163163

164+
// This is a default constructor in a class or struct declared in source.
165+
private bool IsDefault =>
166+
Symbol.IsImplicitlyDeclared &&
167+
Symbol.ContainingType.FromSource() &&
168+
Symbol.ContainingType.TypeKind is TypeKind.Class or TypeKind.Struct &&
169+
Symbol.ContainingType.IsSourceDeclaration() &&
170+
!Symbol.ContainingType.IsAnonymousType;
171+
172+
private bool MakeSynthetic => IsPrimary || IsDefault;
173+
164174
[return: NotNullIfNotNull(nameof(constructor))]
165175
public static new Constructor? Create(Context cx, IMethodSymbol? constructor)
166176
{

csharp/extractor/Semmle.Extraction.CSharp/Entities/Statement`1.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,15 @@ internal abstract class Statement<TSyntax> : Statement where TSyntax : CSharpSyn
1010
protected readonly TSyntax Stmt;
1111
private readonly Location location;
1212

13-
protected Statement(Context cx, TSyntax stmt, Kinds.StmtKind kind, IStatementParentEntity parent, int child, Location location)
13+
protected Statement(Context cx, TSyntax stmt, Kinds.StmtKind kind, IStatementParentEntity parent, int child, Location location, bool isCompilerGenerated = false)
1414
: base(cx, kind, parent, child)
1515
{
1616
Stmt = stmt;
1717
this.location = location;
18-
cx.BindComments(this, location.Symbol);
18+
if (!isCompilerGenerated)
19+
{
20+
cx.BindComments(this, location.Symbol);
21+
}
1922
}
2023

2124
protected Statement(Context cx, TSyntax stmt, Kinds.StmtKind kind, IStatementParentEntity parent, int child)

csharp/extractor/Semmle.Extraction.CSharp/Entities/Statements/SyntheticEmptyBlock.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace Semmle.Extraction.CSharp.Entities.Statements
99
internal class SyntheticEmptyBlock : Statement<BlockSyntax>
1010
{
1111
private SyntheticEmptyBlock(Context cx, BlockSyntax block, IStatementParentEntity parent, int child, Location location)
12-
: base(cx, block, StmtKind.BLOCK, parent, child, location) { }
12+
: base(cx, block, StmtKind.BLOCK, parent, child, location, isCompilerGenerated: true) { }
1313

1414
public static SyntheticEmptyBlock Create(Context cx, IStatementParentEntity parent, int child, Location location)
1515
{

csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowDispatch.qll

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,7 @@ private import semmle.code.csharp.frameworks.system.collections.Generic
2020
*/
2121
DotNet::Callable getCallableForDataFlow(DotNet::Callable c) {
2222
exists(DotNet::Callable unboundDecl | unboundDecl = c.getUnboundDeclaration() |
23-
(
24-
result.hasBody()
25-
or
26-
// take synthesized bodies into account, e.g. implicit constructors
27-
// with field initializer assignments
28-
result = any(ControlFlow::Nodes::ElementNode n).getEnclosingCallable()
29-
) and
23+
result.hasBody() and
3024
if unboundDecl.getFile().fromSource()
3125
then
3226
// C# callable with C# implementation in the database

csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected

Lines changed: 60 additions & 1 deletion
Large diffs are not rendered by default.

csharp/ql/test/library-tests/controlflow/graph/Dominance.expected

Lines changed: 464 additions & 4 deletions
Large diffs are not rendered by default.

csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected

Lines changed: 271 additions & 0 deletions
Large diffs are not rendered by default.

csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected

Lines changed: 71 additions & 0 deletions
Large diffs are not rendered by default.

csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected

Lines changed: 71 additions & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)