forked from OSchip/llvm-project
[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
This commit is contained in:
parent
80de11ed02
commit
ae512b83d5
|
@ -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(),
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);",
|
||||
|
|
Loading…
Reference in New Issue