Index: cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp =================================================================== --- cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp +++ cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp @@ -1085,6 +1085,19 @@ return true; } +/// Determine structural equivalence of two lambda classes. +static bool +IsStructurallyEquivalentLambdas(StructuralEquivalenceContext &Context, + CXXRecordDecl *D1, CXXRecordDecl *D2) { + assert(D1->isLambda() && D2->isLambda() && + "Must be called on lambda classes"); + if (!IsStructurallyEquivalent(Context, D1->getLambdaCallOperator(), + D2->getLambdaCallOperator())) + return false; + + return true; +} + /// Determine structural equivalence of two records. static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, RecordDecl *D1, RecordDecl *D2) { @@ -1166,6 +1179,13 @@ D1CXX->getASTContext().getExternalSource()->CompleteType(D1CXX); } + if (D1CXX->isLambda() != D2CXX->isLambda()) + return false; + if (D1CXX->isLambda()) { + if (!IsStructurallyEquivalentLambdas(Context, D1CXX, D2CXX)) + return false; + } + if (D1CXX->getNumBases() != D2CXX->getNumBases()) { if (Context.Complain) { Context.Diag2(D2->getLocation(), Index: cfe/trunk/unittests/AST/ASTImporterTest.cpp =================================================================== --- cfe/trunk/unittests/AST/ASTImporterTest.cpp +++ cfe/trunk/unittests/AST/ASTImporterTest.cpp @@ -5122,6 +5122,22 @@ EXPECT_EQ(ToLSize, FromLSize); } +TEST_P(ASTImporterOptionSpecificTestBase, LambdaInGlobalScope) { + Decl *FromTU = getTuDecl( + R"( + auto l1 = [](unsigned lp) { return 1; }; + auto l2 = [](int lp) { return 2; }; + int f(int p) { + return l1(p) + l2(p); + } + )", + Lang_CXX11, "input0.cc"); + FunctionDecl *FromF = FirstDeclMatcher().match( + FromTU, functionDecl(hasName("f"))); + FunctionDecl *ToF = Import(FromF, Lang_CXX11); + EXPECT_TRUE(ToF); +} + struct LLDBLookupTest : ASTImporterOptionSpecificTestBase { LLDBLookupTest() { Creator = [](ASTContext &ToContext, FileManager &ToFileManager, Index: cfe/trunk/unittests/AST/StructuralEquivalenceTest.cpp =================================================================== --- cfe/trunk/unittests/AST/StructuralEquivalenceTest.cpp +++ cfe/trunk/unittests/AST/StructuralEquivalenceTest.cpp @@ -797,6 +797,58 @@ EXPECT_FALSE(testStructuralMatch(t)); } +struct StructuralEquivalenceLambdaTest : StructuralEquivalenceTest {}; + +TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithDifferentMethods) { + // Get the LambdaExprs, unfortunately we can't match directly the underlying + // implicit CXXRecordDecl of the Lambda classes. + auto t = makeDecls( + "void f() { auto L0 = [](int){}; }", + "void f() { auto L1 = [](){}; }", + Lang_CXX11, + lambdaExpr(), + lambdaExpr()); + CXXRecordDecl *L0 = get<0>(t)->getLambdaClass(); + CXXRecordDecl *L1 = get<1>(t)->getLambdaClass(); + EXPECT_FALSE(testStructuralMatch(L0, L1)); +} + +TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithEqMethods) { + auto t = makeDecls( + "void f() { auto L0 = [](int){}; }", + "void f() { auto L1 = [](int){}; }", + Lang_CXX11, + lambdaExpr(), + lambdaExpr()); + CXXRecordDecl *L0 = get<0>(t)->getLambdaClass(); + CXXRecordDecl *L1 = get<1>(t)->getLambdaClass(); + EXPECT_TRUE(testStructuralMatch(L0, L1)); +} + +TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithDifferentFields) { + auto t = makeDecls( + "void f() { char* X; auto L0 = [X](){}; }", + "void f() { float X; auto L1 = [X](){}; }", + Lang_CXX11, + lambdaExpr(), + lambdaExpr()); + CXXRecordDecl *L0 = get<0>(t)->getLambdaClass(); + CXXRecordDecl *L1 = get<1>(t)->getLambdaClass(); + EXPECT_FALSE(testStructuralMatch(L0, L1)); +} + +TEST_F(StructuralEquivalenceLambdaTest, LambdaClassesWithEqFields) { + auto t = makeDecls( + "void f() { float X; auto L0 = [X](){}; }", + "void f() { float X; auto L1 = [X](){}; }", + Lang_CXX11, + lambdaExpr(), + lambdaExpr()); + CXXRecordDecl *L0 = get<0>(t)->getLambdaClass(); + CXXRecordDecl *L1 = get<1>(t)->getLambdaClass(); + EXPECT_TRUE(testStructuralMatch(L0, L1)); +} + TEST_F(StructuralEquivalenceTest, CompareSameDeclWithMultiple) { auto t = makeNamedDecls( "struct A{ }; struct B{ }; void foo(A a, A b);",