Browse Source

Fix the passing of std::string by value

std::string has a non-trivial copy constructor which was erroneously ignored.

Fixes #867.

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
bug-pass-const-char-star-no-copy
Dimitar Dobrev 6 years ago
parent
commit
547a9f2819
  1. 8
      src/CppParser/Parser.cpp
  2. 57
      src/Generator/Passes/IgnoreSystemDeclarationsPass.cs
  3. 1
      tests/CSharp/CSharp.Tests.cs
  4. 2
      tests/Common/Common.Tests.cs

8
src/CppParser/Parser.cpp

@ -931,12 +931,16 @@ bool Parser::IsSupported(const clang::CXXMethodDecl* MD) @@ -931,12 +931,16 @@ bool Parser::IsSupported(const clang::CXXMethodDecl* MD)
{
using namespace clang;
auto CopyCtor = llvm::dyn_cast<CXXConstructorDecl>(MD);
return !c->getSourceManager().isInSystemHeader(MD->getBeginLoc()) ||
(isa<CXXConstructorDecl>(MD) && MD->getNumParams() == 0) ||
(CopyCtor && (MD->getNumParams() == 0 ||
(CopyCtor->isCopyConstructor() && !CopyCtor->isTrivial()))) ||
isa<CXXDestructorDecl>(MD) ||
(MD->getDeclName().isIdentifier() &&
((MD->getName() == "c_str" && MD->getNumParams() == 0) ||
(MD->getName() == "assign" && MD->getNumParams() == 1)) &&
(MD->getName() == "assign" && MD->getNumParams() == 1 &&
MD->parameters()[0]->getType()->isPointerType())) &&
supportedStdTypes.find(MD->getParent()->getName()) !=
supportedStdTypes.end());
}

57
src/Generator/Passes/IgnoreSystemDeclarationsPass.cs

@ -55,66 +55,21 @@ namespace CppSharp.Passes @@ -55,66 +55,21 @@ namespace CppSharp.Passes
switch (@class.Name)
{
case "basic_string":
foreach (var method in @class.Methods.Where(m => !m.IsDestructor &&
m.OriginalName != "c_str" && m.OriginalName != "assign"))
method.ExplicitlyIgnore();
foreach (var basicString in GetCharSpecializations(@class))
{
basicString.GenerationKind = GenerationKind.Generate;
foreach (var method in basicString.Methods)
{
if (method.IsDestructor || method.OriginalName == "c_str" ||
(method.OriginalName == "assign" &&
method.Parameters.Count == 1 &&
method.Parameters[0].Type.IsPointerToPrimitiveType()) ||
(method.IsConstructor &&
!method.Parameters.Where(p => p.Kind == ParameterKind.Regular).Any()))
{
method.GenerationKind = GenerationKind.Generate;
method.Namespace.GenerationKind = GenerationKind.Generate;
method.InstantiatedFrom.GenerationKind = GenerationKind.Generate;
method.InstantiatedFrom.Namespace.GenerationKind = GenerationKind.Generate;
}
else
{
method.ExplicitlyIgnore();
}
}
}
break;
case "allocator":
foreach (var method in @class.Methods)
method.ExplicitlyIgnore();
foreach (var allocator in GetCharSpecializations(@class))
{
foreach (var method in allocator.Methods)
method.ExplicitlyIgnore();
allocator.GenerationKind = GenerationKind.Generate;
allocator.TemplatedDecl.TemplatedDecl.GenerationKind = GenerationKind.Generate;
allocator.GenerationKind = GenerationKind.Generate;
}
break;
case "char_traits":
foreach (var method in @class.Methods)
method.ExplicitlyIgnore();
foreach (var charTraits in GetCharSpecializations(@class))
@class.GenerationKind = GenerationKind.Generate;
foreach (var specialization in from s in @class.Specializations
let arg = s.Arguments[0].Type.Type.Desugar()
where arg.IsPrimitiveType(PrimitiveType.Char)
select s)
{
foreach (var method in charTraits.Methods)
method.ExplicitlyIgnore();
charTraits.GenerationKind = GenerationKind.Generate;
charTraits.TemplatedDecl.TemplatedDecl.GenerationKind = GenerationKind.Generate;
specialization.GenerationKind = GenerationKind.Generate;
}
break;
}
return true;
}
private static IEnumerable<ClassTemplateSpecialization> GetCharSpecializations(Class @class)
{
return @class.Specializations.Where(s =>
s.Arguments[0].Type.Type.Desugar().IsPrimitiveType(PrimitiveType.Char));
}
public override bool VisitEnumDecl(Enumeration @enum)
{
if (!base.VisitEnumDecl(@enum))

1
tests/CSharp/CSharp.Tests.cs

@ -606,6 +606,7 @@ public unsafe class CSharpTests : GeneratorTestFixture @@ -606,6 +606,7 @@ public unsafe class CSharpTests : GeneratorTestFixture
}
}
[Test]
public void TestStdStringConstant()
{
Assert.That(CSharp.HasFreeConstant.AnotherUnit.STD_STRING_CONSTANT, Is.EqualTo("test"));

2
tests/Common/Common.Tests.cs

@ -829,7 +829,7 @@ This is a very long string. This is a very long string. This is a very long stri @@ -829,7 +829,7 @@ This is a very long string. This is a very long string. This is a very long stri
}
}
[Ignore("https://github.com/mono/CppSharp/issues/867")]
[Test]
public void TestStdStringPassedByValue()
{
// when C++ memory is deleted, it's only marked as free but not immediadely freed

Loading…
Cancel
Save