summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/AST/ASTStructuralEquivalence.cpp20
-rw-r--r--clang/unittests/AST/ASTImporterTest.cpp16
-rw-r--r--clang/unittests/AST/StructuralEquivalenceTest.cpp52
3 files changed, 88 insertions, 0 deletions
diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp
index bb2e353eeef..912db3c130c 100644
--- a/clang/lib/AST/ASTStructuralEquivalence.cpp
+++ b/clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -1085,6 +1085,19 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
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 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
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(),
diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp
index 8b2f7c5b240..6ea350cc726 100644
--- a/clang/unittests/AST/ASTImporterTest.cpp
+++ b/clang/unittests/AST/ASTImporterTest.cpp
@@ -5122,6 +5122,22 @@ TEST_P(ASTImporterOptionSpecificTestBase, LambdaInFunctionParam) {
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,
diff --git a/clang/unittests/AST/StructuralEquivalenceTest.cpp b/clang/unittests/AST/StructuralEquivalenceTest.cpp
index 63757987e11..cdb55d90b9d 100644
--- a/clang/unittests/AST/StructuralEquivalenceTest.cpp
+++ b/clang/unittests/AST/StructuralEquivalenceTest.cpp
@@ -797,6 +797,58 @@ TEST_F(StructuralEquivalenceRecordTest, RecordsWithDifferentBody) {
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);",
OpenPOWER on IntegriCloud