Skip to content

Commit 547a9f2

Browse files
committed
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 <[email protected]>
1 parent d90d328 commit 547a9f2

File tree

4 files changed

+14
-54
lines changed

4 files changed

+14
-54
lines changed

src/CppParser/Parser.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -931,12 +931,16 @@ bool Parser::IsSupported(const clang::CXXMethodDecl* MD)
931931
{
932932
using namespace clang;
933933

934+
auto CopyCtor = llvm::dyn_cast<CXXConstructorDecl>(MD);
935+
934936
return !c->getSourceManager().isInSystemHeader(MD->getBeginLoc()) ||
935-
(isa<CXXConstructorDecl>(MD) && MD->getNumParams() == 0) ||
937+
(CopyCtor && (MD->getNumParams() == 0 ||
938+
(CopyCtor->isCopyConstructor() && !CopyCtor->isTrivial()))) ||
936939
isa<CXXDestructorDecl>(MD) ||
937940
(MD->getDeclName().isIdentifier() &&
938941
((MD->getName() == "c_str" && MD->getNumParams() == 0) ||
939-
(MD->getName() == "assign" && MD->getNumParams() == 1)) &&
942+
(MD->getName() == "assign" && MD->getNumParams() == 1 &&
943+
MD->parameters()[0]->getType()->isPointerType())) &&
940944
supportedStdTypes.find(MD->getParent()->getName()) !=
941945
supportedStdTypes.end());
942946
}

src/Generator/Passes/IgnoreSystemDeclarationsPass.cs

Lines changed: 6 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -55,66 +55,21 @@ public override bool VisitClassDecl(Class @class)
5555
switch (@class.Name)
5656
{
5757
case "basic_string":
58-
foreach (var method in @class.Methods.Where(m => !m.IsDestructor &&
59-
m.OriginalName != "c_str" && m.OriginalName != "assign"))
60-
method.ExplicitlyIgnore();
61-
foreach (var basicString in GetCharSpecializations(@class))
62-
{
63-
basicString.GenerationKind = GenerationKind.Generate;
64-
foreach (var method in basicString.Methods)
65-
{
66-
if (method.IsDestructor || method.OriginalName == "c_str" ||
67-
(method.OriginalName == "assign" &&
68-
method.Parameters.Count == 1 &&
69-
method.Parameters[0].Type.IsPointerToPrimitiveType()) ||
70-
(method.IsConstructor &&
71-
!method.Parameters.Where(p => p.Kind == ParameterKind.Regular).Any()))
72-
{
73-
method.GenerationKind = GenerationKind.Generate;
74-
method.Namespace.GenerationKind = GenerationKind.Generate;
75-
method.InstantiatedFrom.GenerationKind = GenerationKind.Generate;
76-
method.InstantiatedFrom.Namespace.GenerationKind = GenerationKind.Generate;
77-
}
78-
else
79-
{
80-
method.ExplicitlyIgnore();
81-
}
82-
}
83-
}
84-
break;
8558
case "allocator":
86-
foreach (var method in @class.Methods)
87-
method.ExplicitlyIgnore();
88-
foreach (var allocator in GetCharSpecializations(@class))
89-
{
90-
foreach (var method in allocator.Methods)
91-
method.ExplicitlyIgnore();
92-
allocator.GenerationKind = GenerationKind.Generate;
93-
allocator.TemplatedDecl.TemplatedDecl.GenerationKind = GenerationKind.Generate;
94-
allocator.GenerationKind = GenerationKind.Generate;
95-
}
96-
break;
9759
case "char_traits":
98-
foreach (var method in @class.Methods)
99-
method.ExplicitlyIgnore();
100-
foreach (var charTraits in GetCharSpecializations(@class))
60+
@class.GenerationKind = GenerationKind.Generate;
61+
foreach (var specialization in from s in @class.Specializations
62+
let arg = s.Arguments[0].Type.Type.Desugar()
63+
where arg.IsPrimitiveType(PrimitiveType.Char)
64+
select s)
10165
{
102-
foreach (var method in charTraits.Methods)
103-
method.ExplicitlyIgnore();
104-
charTraits.GenerationKind = GenerationKind.Generate;
105-
charTraits.TemplatedDecl.TemplatedDecl.GenerationKind = GenerationKind.Generate;
66+
specialization.GenerationKind = GenerationKind.Generate;
10667
}
10768
break;
10869
}
10970
return true;
11071
}
11172

112-
private static IEnumerable<ClassTemplateSpecialization> GetCharSpecializations(Class @class)
113-
{
114-
return @class.Specializations.Where(s =>
115-
s.Arguments[0].Type.Type.Desugar().IsPrimitiveType(PrimitiveType.Char));
116-
}
117-
11873
public override bool VisitEnumDecl(Enumeration @enum)
11974
{
12075
if (!base.VisitEnumDecl(@enum))

tests/CSharp/CSharp.Tests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,7 @@ public void TestGetEnumFromNativePointer()
606606
}
607607
}
608608

609+
[Test]
609610
public void TestStdStringConstant()
610611
{
611612
Assert.That(CSharp.HasFreeConstant.AnotherUnit.STD_STRING_CONSTANT, Is.EqualTo("test"));

tests/Common/Common.Tests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -829,7 +829,7 @@ This is a very long string. This is a very long string. This is a very long stri
829829
}
830830
}
831831

832-
[Ignore("https://github.com/mono/CppSharp/issues/867")]
832+
[Test]
833833
public void TestStdStringPassedByValue()
834834
{
835835
// when C++ memory is deleted, it's only marked as free but not immediadely freed

0 commit comments

Comments
 (0)