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) {
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(),
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<FunctionDecl>().match(
+ FromTU, functionDecl(hasName("f")));
+ FunctionDecl *ToF = Import(FromF, Lang_CXX11);
+ EXPECT_TRUE(ToF);
+}
+
struct LLDBLookupTest : ASTImporterOptionSpecificTestBase {
LLDBLookupTest() {
Creator = [](ASTContext &ToContext, FileManager &ToFileManager,
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<LambdaExpr>(
+ "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<LambdaExpr>(
+ "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<LambdaExpr>(
+ "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<LambdaExpr>(
+ "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);",