balazske created this revision.
Herald added subscribers: cfe-commits, martong.
Herald added a reviewer: a.sidorin.

At equality check of fields without name the index of fields is compared.
At determining the index of a field all fields of the parent context
should be loaded from external source to find the field at all.


Repository:
  rC Clang

https://reviews.llvm.org/D49796

Files:
  lib/AST/ASTImporter.cpp
  test/ASTMerge/unnamed_fields/Inputs/il.cpp
  test/ASTMerge/unnamed_fields/test.cpp
  unittests/AST/ASTImporterTest.cpp


Index: unittests/AST/ASTImporterTest.cpp
===================================================================
--- unittests/AST/ASTImporterTest.cpp
+++ unittests/AST/ASTImporterTest.cpp
@@ -2612,6 +2612,45 @@
       R1, recordDecl(has(fieldDecl(hasName("next"))))));
 }
 
+TEST_P(ASTImporterTestBase, ImportUnnamedFieldsInCorrectOrder) {
+  Decl *FromTU = getTuDecl(
+      R"(
+      void f(int X, int Y, bool Z) {
+        (void)[X, Y, Z] { (void)Z; };
+      }
+      )",
+      Lang_CXX11, "input0.cc");
+  auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
+      FromTU, functionDecl(hasName("f")));
+  auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11));
+  EXPECT_TRUE(ToF);
+
+  CXXRecordDecl *FromLambda =
+      cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>(
+          FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();
+
+  auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11));
+  EXPECT_TRUE(ToLambda);
+
+  // Check if the fields of the lambda class are imported in correct order.
+  unsigned FromIndex = 0u;
+  for (auto *FromField : FromLambda->fields()) {
+    ASSERT_FALSE(FromField->getDeclName());
+    auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11));
+    EXPECT_TRUE(ToField);
+    unsigned ToIndex = 0u;
+    for (auto *F : ToLambda->fields()) {
+      if (F == ToField)
+        break;
+      ++ToIndex;
+    }
+    EXPECT_EQ(ToIndex, FromIndex);
+    ++FromIndex;
+  }
+
+  EXPECT_EQ(FromIndex, 3u);
+}
+
 struct DeclContextTest : ASTImporterTestBase {};
 
 TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
Index: test/ASTMerge/unnamed_fields/test.cpp
===================================================================
--- /dev/null
+++ test/ASTMerge/unnamed_fields/test.cpp
@@ -0,0 +1,3 @@
+// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/il.cpp
+// RUN: %clang_cc1 -ast-merge %t.1.ast -fsyntax-only %s 2>&1 | FileCheck 
--allow-empty %s
+// CHECK-NOT: warning: field '' declared with incompatible types in different 
translation units ('bool' vs. 'int')
Index: test/ASTMerge/unnamed_fields/Inputs/il.cpp
===================================================================
--- /dev/null
+++ test/ASTMerge/unnamed_fields/Inputs/il.cpp
@@ -0,0 +1,3 @@
+void f(int X, int Y, bool Z) {
+  auto x = [X, Y, Z] { (void)Z; };
+}
Index: lib/AST/ASTImporter.cpp
===================================================================
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -2829,15 +2829,17 @@
     return 0;
 
   unsigned Index = 1;
-  for (const auto *D : Owner->noload_decls()) {
+  for (const auto *D : Owner->decls()) {
     if (D == F)
       return Index;
 
     if (isa<FieldDecl>(*D) || isa<IndirectFieldDecl>(*D))
       ++Index;
   }
 
-  return Index;
+  assert(false && "Field was not found in its parent context.");
+
+  return 0;
 }
 
 Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) {


Index: unittests/AST/ASTImporterTest.cpp
===================================================================
--- unittests/AST/ASTImporterTest.cpp
+++ unittests/AST/ASTImporterTest.cpp
@@ -2612,6 +2612,45 @@
       R1, recordDecl(has(fieldDecl(hasName("next"))))));
 }
 
+TEST_P(ASTImporterTestBase, ImportUnnamedFieldsInCorrectOrder) {
+  Decl *FromTU = getTuDecl(
+      R"(
+      void f(int X, int Y, bool Z) {
+        (void)[X, Y, Z] { (void)Z; };
+      }
+      )",
+      Lang_CXX11, "input0.cc");
+  auto *FromF = FirstDeclMatcher<FunctionDecl>().match(
+      FromTU, functionDecl(hasName("f")));
+  auto *ToF = cast_or_null<FunctionDecl>(Import(FromF, Lang_CXX11));
+  EXPECT_TRUE(ToF);
+
+  CXXRecordDecl *FromLambda =
+      cast<LambdaExpr>(cast<CStyleCastExpr>(cast<CompoundStmt>(
+          FromF->getBody())->body_front())->getSubExpr())->getLambdaClass();
+
+  auto *ToLambda = cast_or_null<CXXRecordDecl>(Import(FromLambda, Lang_CXX11));
+  EXPECT_TRUE(ToLambda);
+
+  // Check if the fields of the lambda class are imported in correct order.
+  unsigned FromIndex = 0u;
+  for (auto *FromField : FromLambda->fields()) {
+    ASSERT_FALSE(FromField->getDeclName());
+    auto *ToField = cast_or_null<FieldDecl>(Import(FromField, Lang_CXX11));
+    EXPECT_TRUE(ToField);
+    unsigned ToIndex = 0u;
+    for (auto *F : ToLambda->fields()) {
+      if (F == ToField)
+        break;
+      ++ToIndex;
+    }
+    EXPECT_EQ(ToIndex, FromIndex);
+    ++FromIndex;
+  }
+
+  EXPECT_EQ(FromIndex, 3u);
+}
+
 struct DeclContextTest : ASTImporterTestBase {};
 
 TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {
Index: test/ASTMerge/unnamed_fields/test.cpp
===================================================================
--- /dev/null
+++ test/ASTMerge/unnamed_fields/test.cpp
@@ -0,0 +1,3 @@
+// RUN: %clang_cc1 -emit-pch -o %t.1.ast %S/Inputs/il.cpp
+// RUN: %clang_cc1 -ast-merge %t.1.ast -fsyntax-only %s 2>&1 | FileCheck --allow-empty %s
+// CHECK-NOT: warning: field '' declared with incompatible types in different translation units ('bool' vs. 'int')
Index: test/ASTMerge/unnamed_fields/Inputs/il.cpp
===================================================================
--- /dev/null
+++ test/ASTMerge/unnamed_fields/Inputs/il.cpp
@@ -0,0 +1,3 @@
+void f(int X, int Y, bool Z) {
+  auto x = [X, Y, Z] { (void)Z; };
+}
Index: lib/AST/ASTImporter.cpp
===================================================================
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -2829,15 +2829,17 @@
     return 0;
 
   unsigned Index = 1;
-  for (const auto *D : Owner->noload_decls()) {
+  for (const auto *D : Owner->decls()) {
     if (D == F)
       return Index;
 
     if (isa<FieldDecl>(*D) || isa<IndirectFieldDecl>(*D))
       ++Index;
   }
 
-  return Index;
+  assert(false && "Field was not found in its parent context.");
+
+  return 0;
 }
 
 Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to