Skip to content

Commit

Permalink
Merge pull request #348 from andreasfertig/fixIssue347
Browse files Browse the repository at this point in the history
Fixed #347: Use `const &` or `&/&&` as constructor parameters for lambdas
  • Loading branch information
andreasfertig committed Sep 26, 2020
2 parents ebfe72e + abea206 commit bc02139
Show file tree
Hide file tree
Showing 21 changed files with 162 additions and 146 deletions.
56 changes: 47 additions & 9 deletions CodeGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2712,8 +2712,13 @@ void CodeGenerator::InsertArg(const CXXRecordDecl* stmt)
}

std::string refRef{};
std::string addConst{};
bool byConstRef{false};

const auto& fieldName{StrCat(isThis ? "__" : "", name)};
const auto& fieldDeclType{fd->getType()};

std::string fname = StrCat("_", name);

// Special handling for lambdas with init captures which contain a move. In such a case, copy the
// initial move statement and make the variable a &&.
Expand All @@ -2729,27 +2734,61 @@ void CodeGenerator::InsertArg(const CXXRecordDecl* stmt)
}

refRef = "&& ";

ctorInitializerList.push_back(StrCat(fieldName, "{", ofm.GetString(), "}"));
} else {

ctorInitializerList.push_back(StrCat(fieldName, "{", "_", name, "}"));
fname = ofm.GetString();

// If it is not an object, check for other conditions why we take the variable by const &/&& in the
// ctor
} else if(not fieldDeclType->isReferenceType() && not fieldDeclType->isAnyPointerType() &&
not fieldDeclType->isUndeducedAutoType()) {
byConstRef = true;
refRef = "& ";
const auto* exprWithoutImpCasts = expr->IgnoreParenImpCasts();

// treat a move of a primitive type
if(exprWithoutImpCasts->isXValue()) {
refRef = "&& ";
byConstRef = false;

OutputFormatHelper ofm{};
LambdaInitCaptureCodeGenerator codeGenerator{ofm, mLambdaStack, name};
codeGenerator.InsertArg(expr);

fname = ofm.GetString();

} else if(exprWithoutImpCasts
->isRValue() // If we are looking at an rvalue (temporary) we need a const ref
|| exprWithoutImpCasts->getType().isConstQualified() // If the captured variable is const
// we can take it only by const ref

) {
addConst = "const ";
}
}

ctorInitializerList.push_back(StrCat(fieldName, "{", fname, "}"));

if(not isThis && expr) {
OutputFormatHelper ofm{};
CodeGenerator codeGenerator{ofm, mLambdaStack};
codeGenerator.InsertArg(expr);

if(const auto* ctorExpr = dyn_cast_or_null<CXXConstructExpr>(expr);
ctorExpr && byConstRef && (1 == ctorExpr->getNumArgs())) {
codeGenerator.InsertArg(ctorExpr->getArg(0));

} else {
codeGenerator.InsertArg(expr);
}

ctorArguments.append(ofm.GetString());
} else {
if(isThis && not fd->getType()->isPointerType()) {
if(isThis && not fieldDeclType->isPointerType()) {
ctorArguments.append("*");
}

ctorArguments.append(name);
}

mOutputFormatHelper.Append(GetTypeNameAsParameter(fd->getType(), StrCat(refRef, "_", name)));
mOutputFormatHelper.Append(addConst, GetTypeNameAsParameter(fieldDeclType, StrCat(refRef, "_", name)));
};

llvm::DenseMap<const VarDecl*, FieldDecl*> captures{};
Expand Down Expand Up @@ -2815,7 +2854,6 @@ void CodeGenerator::InsertArg(const CXXRecordDecl* stmt)
} else {
mLambdaStack.back().inits().append(ctorArguments);
}

} else {
mOutputFormatHelper.CloseScope(OutputFormatHelper::NoNewLineBefore::Yes);
}
Expand Down
6 changes: 3 additions & 3 deletions tests/Issue2.expect
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ int main()
int c;
public:
// inline __lambda_20_16(const __lambda_20_16 &) = delete;
__lambda_20_16(Movable && _x, int _c)
__lambda_20_16(Movable && _x, int & _c)
: x{std::move(_x)}
, c{_c}
{}
Expand All @@ -59,8 +59,8 @@ int main()
int c;

public:
__lambda_24_16(int _c)
: c{_c}
__lambda_24_16(int && _c)
: c{std::move(_c)}
{}

};
Expand Down
6 changes: 6 additions & 0 deletions tests/Issue347.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include <string>

int main() {
std::string str {"Hello World"};
auto foo = [str]() { };
}
25 changes: 25 additions & 0 deletions tests/Issue347.expect
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include <string>

int main()
{
std::string str = std::basic_string<char>{"Hello World"};

class __lambda_5_12
{
public:
inline /*constexpr */ void operator()() const
{
}

private:
std::basic_string<char> str;
public:
__lambda_5_12(const std::basic_string<char> & _str)
: str{_str}
{}

};

__lambda_5_12 foo = __lambda_5_12{str};
}

6 changes: 6 additions & 0 deletions tests/Issue347_2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include <string>

int main() {
const std::string str {"Hello World"};
auto foo = [str]() { };
}
25 changes: 25 additions & 0 deletions tests/Issue347_2.expect
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include <string>

int main()
{
const std::string str = std::basic_string<char>{"Hello World"};

class __lambda_5_12
{
public:
inline /*constexpr */ void operator()() const
{
}

private:
const std::basic_string<char> str;
public:
__lambda_5_12(const const std::basic_string<char> & _str)
: str{_str}
{}

};

__lambda_5_12 foo = __lambda_5_12{str};
}

2 changes: 1 addition & 1 deletion tests/Issue4.expect
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ int main()
char uuu;

public:
__lambda_9_11(char _uuu)
__lambda_9_11(const char & _uuu)
: uuu{_uuu}
{}

Expand Down
2 changes: 1 addition & 1 deletion tests/Issue46.expect
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class __lambda_5_11
int a;

public:
__lambda_5_11(int _a)
__lambda_5_11(const int & _a)
: a{_a}
{}

Expand Down
4 changes: 2 additions & 2 deletions tests/Issue64.expect
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ void func(const std::basic_string<char> & arg)
private:
const std::basic_string<char> arg;
public:
__lambda_5_11(const std::basic_string<char> _arg)
__lambda_5_11(const const std::basic_string<char> & _arg)
: arg{_arg}
{}

} __lambda_5_11{std::basic_string<char>(arg)};
} __lambda_5_11{arg};

unsigned long s = __lambda_5_11.operator()();
}
Expand Down
2 changes: 1 addition & 1 deletion tests/LambdaConstexprTest.expect
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ void Test()
const int Size;

public:
__lambda_4_18(const int _Size)
__lambda_4_18(const const int & _Size)
: Size{_Size}
{}

Expand Down
2 changes: 1 addition & 1 deletion tests/LambdaHandler4Test.expect
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class Foo
Foo __this;

public:
__lambda_14_18(Foo _this)
__lambda_14_18(const Foo & _this)
: __this{_this}
{}

Expand Down
4 changes: 2 additions & 2 deletions tests/LambdaHandlerTest.expect
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ int main()
int b;

public:
__lambda_46_20(int _foo, int _b)
__lambda_46_20(int & _foo, int & _b)
: foo{_foo}
, b{_b}
{}
Expand All @@ -291,7 +291,7 @@ int main()
int b;

public:
__lambda_48_20(int _foo, int _b)
__lambda_48_20(int & _foo, int & _b)
: foo{_foo}
, b{_b}
{}
Expand Down
2 changes: 1 addition & 1 deletion tests/LambdaImplicitCaptureTest.expect
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ int main()
int x;

public:
__lambda_7_14(int _x)
__lambda_7_14(int & _x)
: x{_x}
{}

Expand Down
14 changes: 7 additions & 7 deletions tests/LambdaInLamda2Test.cerr
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@
.tmp.cpp:17:17: note: to match this '('
__lambda_4_5(
^
.tmp.cpp:53:5: error: unknown type name 'S'
S _s)
^
.tmp.cpp:53:9: error: expected ';' at end of declaration list
S _s)
^
;
.tmp.cpp:53:11: error: unknown type name 'S'
const S & _s)
^
.tmp.cpp:53:17: error: expected ';' at end of declaration list
const S & _s)
^
;
.tmp.cpp:59:33: error: use of undeclared identifier '__lambda_5_7'
__lambda_4_5 l = __lambda_4_5{__lambda_5_7.operator()()};
^
Expand Down
2 changes: 1 addition & 1 deletion tests/LambdaInLamda2Test.expect
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ int main()

} __lambda_5_7{};

S _s)
const S & _s)
: s{_s}
{}

Expand Down
2 changes: 1 addition & 1 deletion tests/LambdaPackExpansionTest.expect
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ void f2<int, int, int, int, int>(int __args0, int __args1, int __args2, int __ar
int __args4;

public:
__lambda_19_15(int ___args0, int ___args1, int ___args2, int ___args3, int ___args4)
__lambda_19_15(int & ___args0, int & ___args1, int & ___args2, int & ___args3, int & ___args4)
: __args0{___args0}
, __args1{___args1}
, __args2{___args2}
Expand Down
5 changes: 5 additions & 0 deletions tests/LambdaWithConstCapture.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
int main()
{
const char a{ 2 };
auto&& l=[ uuu = a]{ };
}
24 changes: 24 additions & 0 deletions tests/LambdaWithConstCapture.expect
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
int main()
{
const char a = {2};

class __lambda_4_11
{
public:
inline /*constexpr */ void operator()() const
{
}

private:
char uuu;

public:
__lambda_4_11(const char & _uuu)
: uuu{_uuu}
{}

};

__lambda_4_11 && l = __lambda_4_11{a};
}

6 changes: 3 additions & 3 deletions tests/StdInitializerList2Test.expect
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@ int main(int argc, const char **)
std::initializer_list<int> list;

public:
__lambda_10_17(std::initializer_list<int> _list)
__lambda_10_17(const std::initializer_list<int> & _list)
: list{_list}
{}

};

__lambda_10_17 lamb = __lambda_10_17{std::initializer_list<int>(list)};
__lambda_10_17 lamb = __lambda_10_17{list};
std::initializer_list<int> l = lamb.operator()();

class __lambda_14_18
Expand All @@ -43,7 +43,7 @@ int main(int argc, const char **)
int x;

public:
__lambda_14_18(int _i, int _x)
__lambda_14_18(int & _i, int & _x)
: i{_i}
, x{_x}
{}
Expand Down
41 changes: 0 additions & 41 deletions tests/concepts2Test.cpp

This file was deleted.

Loading

0 comments on commit bc02139

Please sign in to comment.