Author: martong Date: Wed Jul 17 07:40:09 2019 New Revision: 366332 URL: http://llvm.org/viewvc/llvm-project?rev=366332&view=rev Log: [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 Modified: cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp cfe/trunk/unittests/AST/ASTImporterTest.cpp cfe/trunk/unittests/AST/StructuralEquivalenceTest.cpp Modified: cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp?rev=366332&r1=366331&r2=366332&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp (original) +++ cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp Wed Jul 17 07:40:09 2019 @@ -1085,6 +1085,19 @@ static bool IsStructurallyEquivalent(Str 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(Str 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(), Modified: cfe/trunk/unittests/AST/ASTImporterTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/ASTImporterTest.cpp?rev=366332&r1=366331&r2=366332&view=diff ============================================================================== --- cfe/trunk/unittests/AST/ASTImporterTest.cpp (original) +++ cfe/trunk/unittests/AST/ASTImporterTest.cpp Wed Jul 17 07:40:09 2019 @@ -5122,6 +5122,22 @@ TEST_P(ASTImporterOptionSpecificTestBase 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, Modified: cfe/trunk/unittests/AST/StructuralEquivalenceTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/StructuralEquivalenceTest.cpp?rev=366332&r1=366331&r2=366332&view=diff ============================================================================== --- cfe/trunk/unittests/AST/StructuralEquivalenceTest.cpp (original) +++ cfe/trunk/unittests/AST/StructuralEquivalenceTest.cpp Wed Jul 17 07:40:09 2019 @@ -797,6 +797,58 @@ TEST_F(StructuralEquivalenceRecordTest, 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);", _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits