Skip to content

Commit e73805f

Browse files
author
Gabor Marton
committed
[ASTImporter] Fix import of lambda in function param
Summary: The current import implementation fails to import the definition of a lambda class if the lambda class is defined in a function param. E.g., the lambda class below will be imported without any methods: ``` template <typename F> void f(F L = [](){}) {} ``` Reviewers: a_sidorin, a.sidorin, shafik Subscribers: rnkovacs, dkrupp, Szelethus, gamesh411, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D64073 llvm-svn: 365315
1 parent 0752d12 commit e73805f

File tree

2 files changed

+51
-11
lines changed

2 files changed

+51
-11
lines changed

clang/lib/AST/ASTImporter.cpp

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1708,8 +1708,18 @@ static Error setTypedefNameForAnonDecl(TagDecl *From, TagDecl *To,
17081708
Error ASTNodeImporter::ImportDefinition(
17091709
RecordDecl *From, RecordDecl *To, ImportDefinitionKind Kind) {
17101710
if (To->getDefinition() || To->isBeingDefined()) {
1711-
if (Kind == IDK_Everything)
1712-
return ImportDeclContext(From, /*ForceImport=*/true);
1711+
if (Kind == IDK_Everything ||
1712+
// In case of lambdas, the class already has a definition ptr set, but
1713+
// the contained decls are not imported yet. Also, isBeingDefined was
1714+
// set in CXXRecordDecl::CreateLambda. We must import the contained
1715+
// decls here and finish the definition.
1716+
(To->isLambda() && shouldForceImportDeclContext(Kind))) {
1717+
Error Result = ImportDeclContext(From, /*ForceImport=*/true);
1718+
// Finish the definition of the lambda, set isBeingDefined to false.
1719+
if (To->isLambda())
1720+
To->completeDefinition();
1721+
return Result;
1722+
}
17131723

17141724
return Error::success();
17151725
}
@@ -7422,19 +7432,10 @@ ExpectedStmt ASTNodeImporter::VisitLambdaExpr(LambdaExpr *E) {
74227432
return ToClassOrErr.takeError();
74237433
CXXRecordDecl *ToClass = *ToClassOrErr;
74247434

7425-
// NOTE: lambda classes are created with BeingDefined flag set up.
7426-
// It means that ImportDefinition doesn't work for them and we should fill it
7427-
// manually.
7428-
if (ToClass->isBeingDefined())
7429-
if (Error Err = ImportDeclContext(FromClass, /*ForceImport = */ true))
7430-
return std::move(Err);
7431-
74327435
auto ToCallOpOrErr = import(E->getCallOperator());
74337436
if (!ToCallOpOrErr)
74347437
return ToCallOpOrErr.takeError();
74357438

7436-
ToClass->completeDefinition();
7437-
74387439
SmallVector<LambdaCapture, 8> ToCaptures;
74397440
ToCaptures.reserve(E->capture_size());
74407441
for (const auto &FromCapture : E->captures()) {

clang/unittests/AST/ASTImporterTest.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5083,6 +5083,45 @@ INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
50835083
INSTANTIATE_TEST_CASE_P(ParameterizedTests, CanonicalRedeclChain,
50845084
::testing::Values(ArgVector()), );
50855085

5086+
TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionBody) {
5087+
Decl *FromTU = getTuDecl(
5088+
R"(
5089+
void f() {
5090+
auto L = [](){};
5091+
}
5092+
)",
5093+
Lang_CXX11, "input0.cc");
5094+
auto Pattern = lambdaExpr();
5095+
CXXRecordDecl *FromL =
5096+
FirstDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();
5097+
5098+
auto ToL = Import(FromL, Lang_CXX11);
5099+
unsigned ToLSize = std::distance(ToL->decls().begin(), ToL->decls().end());
5100+
unsigned FromLSize =
5101+
std::distance(FromL->decls().begin(), FromL->decls().end());
5102+
EXPECT_NE(ToLSize, 0u);
5103+
EXPECT_EQ(ToLSize, FromLSize);
5104+
}
5105+
5106+
TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionParam) {
5107+
Decl *FromTU = getTuDecl(
5108+
R"(
5109+
template <typename F>
5110+
void f(F L = [](){}) {}
5111+
)",
5112+
Lang_CXX11, "input0.cc");
5113+
auto Pattern = lambdaExpr();
5114+
CXXRecordDecl *FromL =
5115+
FirstDeclMatcher<LambdaExpr>().match(FromTU, Pattern)->getLambdaClass();
5116+
5117+
auto ToL = Import(FromL, Lang_CXX11);
5118+
unsigned ToLSize = std::distance(ToL->decls().begin(), ToL->decls().end());
5119+
unsigned FromLSize =
5120+
std::distance(FromL->decls().begin(), FromL->decls().end());
5121+
EXPECT_NE(ToLSize, 0u);
5122+
EXPECT_EQ(ToLSize, FromLSize);
5123+
}
5124+
50865125
INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest,
50875126
DefaultTestValuesForRunOptions, );
50885127

0 commit comments

Comments
 (0)