Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions Coder.Test/Languages/CppGeneratedSourceCompilesTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,46 @@ public void AnArrayDeclarationCompilesWhereverAnUnboundedOneMayStand()
});
}

/// <summary>
/// Tests that a class's mutable static fields compile, with and without an initialiser.
/// </summary>
/// <remarks>
/// ISO C++ forbids an in-class initialiser on a non-const static data member, and the generator
/// writes one on every field — the value it was given, or <c>{}</c> when it was given none. Only
/// <c>inline static</c> lets both stand inside the class.
/// </remarks>
[TestMethod]
public void AMutableStaticFieldCompilesInsideAClass()
{
string? compiler = ToolchainHarness.FindOnPath("--version", Compilers);
if (compiler is null)
{
Assert.Inconclusive("No C++ compiler on the path, so nothing was compiled.");
return;
}

SourceFile file = new("statics") { IsHeader = true };
ClassDeclaration config = new("Cfg") { Kind = TypeDeclarationKind.Struct };
config.Members.Add(new FieldDeclaration("count", "int") { IsStatic = true, InitialValue = new LiteralExpression<int>(0) });
config.Members.Add(new FieldDeclaration("limit", "int") { IsStatic = true });
file.Members.Add(config);

ToolchainHarness.InTemporaryDirectory(directory =>
{
File.WriteAllText(Path.Combine(directory, "statics.h"), new CppGenerator().Generate(file));
File.WriteAllText(
Path.Combine(directory, "driver.cpp"),
"#include \"statics.h\"\n\nint main()\n{\n\tCfg::count = Cfg::limit + 1;\n\treturn Cfg::count * 0;\n}\n");

(int exitCode, string output) = ToolchainHarness.Run(
compiler,
"-std=c++20 -Wall -Wextra -pedantic -c driver.cpp -o driver.o",
directory);

Assert.AreEqual(0, exitCode, $"{compiler} rejected the generated header:{Environment.NewLine}{output}");
});
}

/// <summary>
/// Builds a header declaring an array in each position one with no bound may stand in.
/// </summary>
Expand Down
13 changes: 10 additions & 3 deletions Coder/Languages/CppGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@
/// </summary>
/// <remarks>
/// A depth rather than a flag, so a type declared inside a type leaves the count right when it
/// closes. The one thing it decides is whether a constant field says <c>inline</c> or
/// <c>static</c>; see <see cref="SpellStorage"/>.
/// closes. What it decides is how a constant or static field spells its storage; see
/// <see cref="SpellStorage"/>.
/// </remarks>
private int insideType;

Expand Down Expand Up @@ -330,7 +330,7 @@
/// describing a scope.
/// </para>
/// </remarks>
protected override void GenerateClassDeclaration(ClassDeclaration classDecl, CodeBlocker code)

Check warning on line 333 in Coder/Languages/CppGenerator.cs

View workflow job for this annotation

GitHub Actions / Analyze & Release

Refactor this method to reduce its Cognitive Complexity from 17 to the 15 allowed.

Check warning on line 333 in Coder/Languages/CppGenerator.cs

View workflow job for this annotation

GitHub Actions / Analyze & Release

Refactor this method to reduce its Cognitive Complexity from 17 to the 15 allowed.

Check warning on line 333 in Coder/Languages/CppGenerator.cs

View workflow job for this annotation

GitHub Actions / Analyze & Release

Refactor this method to reduce its Cognitive Complexity from 17 to the 15 allowed.

Check warning on line 333 in Coder/Languages/CppGenerator.cs

View workflow job for this annotation

GitHub Actions / Analyze & Release

Refactor this method to reduce its Cognitive Complexity from 17 to the 15 allowed.

Check warning on line 333 in Coder/Languages/CppGenerator.cs

View workflow job for this annotation

GitHub Actions / Analyze & Release

Refactor this method to reduce its Cognitive Complexity from 17 to the 15 allowed.

Check warning on line 333 in Coder/Languages/CppGenerator.cs

View workflow job for this annotation

GitHub Actions / Analyze & Release

Refactor this method to reduce its Cognitive Complexity from 17 to the 15 allowed.

Check warning on line 333 in Coder/Languages/CppGenerator.cs

View workflow job for this annotation

GitHub Actions / Analyze & Release

Refactor this method to reduce its Cognitive Complexity from 17 to the 15 allowed.

Check warning on line 333 in Coder/Languages/CppGenerator.cs

View workflow job for this annotation

GitHub Actions / Analyze & Release

Refactor this method to reduce its Cognitive Complexity from 17 to the 15 allowed.
{
Ensure.NotNull(classDecl);
Ensure.NotNull(code);
Expand Down Expand Up @@ -794,7 +794,14 @@
return insideType > 0 ? "static constexpr " : "inline constexpr ";
}

return field.IsStatic ? "static " : string.Empty;
// A non-const static data member may only carry an in-class initialiser when it is inline,
// and every field is written with one, so inside a type the plain keyword never compiles.
if (field.IsStatic)
{
return insideType > 0 ? "inline static " : "static ";
}

return string.Empty;
}

/// <summary>
Expand Down
Loading