diff options
author | Gabor Marton <gabor.marton@ericsson.com> | 2019-07-17 14:40:09 +0000 |
---|---|---|
committer | Gabor Marton <gabor.marton@ericsson.com> | 2019-07-17 14:40:09 +0000 |
commit | ae512b83d5fc79fb96844ce7cfe4c6a4fee96c9a (patch) | |
tree | de5d9f1e9394279ff59a3e2013f3199284599710 | |
parent | 80de11ed0216a232e224f4b01ab4eb818401f829 (diff) | |
download | bcm5719-llvm-ae512b83d5fc79fb96844ce7cfe4c6a4fee96c9a.tar.gz bcm5719-llvm-ae512b83d5fc79fb96844ce7cfe4c6a4fee96c9a.zip |
[ASTImporter] Fix structural eq of lambdas
Summary:
The structural equivalence check reported false eq between lambda classes
with different parameters in their call signature.
The solution is to check the methods for equality too in case of lambda
classes.
Reviewers: a_sidorin, a.sidorin
Subscribers: rnkovacs, dkrupp, Szelethus, gamesh411, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D64075
llvm-svn: 366332
-rw-r--r-- | clang/lib/AST/ASTStructuralEquivalence.cpp | 20 | ||||
-rw-r--r-- | clang/unittests/AST/ASTImporterTest.cpp | 16 | ||||
-rw-r--r-- | clang/unittests/AST/StructuralEquivalenceTest.cpp | 52 |
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);", |