[PATCH] D44100: [ASTImporter] Reorder fields after structure import is finished

Gabor Marton via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Fri Mar 8 01:44:57 PST 2019


martong updated this revision to Diff 189830.
martong edited the summary of this revision.
martong added a comment.
Herald added a project: clang.

Rebase to master.
There was a conflict in the tests, in ASTImporterTest.cpp.


Repository:
  rC Clang

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D44100/new/

https://reviews.llvm.org/D44100

Files:
  lib/AST/ASTImporter.cpp
  unittests/AST/ASTImporterTest.cpp


Index: unittests/AST/ASTImporterTest.cpp
===================================================================
--- unittests/AST/ASTImporterTest.cpp
+++ unittests/AST/ASTImporterTest.cpp
@@ -1537,7 +1537,7 @@
 }
 
 TEST_P(ASTImporterOptionSpecificTestBase,
-       DISABLED_CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
+       CXXRecordDeclFieldOrderShouldNotDependOnImportOrder) {
   Decl *From, *To;
   std::tie(From, To) = getImportedDecl(
       // The original recursive algorithm of ASTImporter first imports 'c' then
@@ -5517,5 +5517,16 @@
 INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportVariables,
                         DefaultTestValuesForRunOptions, );
 
+TEST_P(ImportDecl, ImportFieldOrder) {
+  MatchVerifier<Decl> Verifier;
+  testImport("struct declToImport {"
+             "  int b = a + 2;"
+             "  int a = 5;"
+             "};",
+             Lang_CXX11, "", Lang_CXX11, Verifier,
+             recordDecl(hasFieldOrder({"b", "a"})));
+}
+
+
 } // end namespace ast_matchers
 } // end namespace clang
Index: lib/AST/ASTImporter.cpp
===================================================================
--- lib/AST/ASTImporter.cpp
+++ lib/AST/ASTImporter.cpp
@@ -1635,13 +1635,61 @@
     auto ToDCOrErr = Importer.ImportContext(FromDC);
     return ToDCOrErr.takeError();
   }
-  llvm::SmallVector<Decl *, 8> ImportedDecls;
+
+  const auto *FromRD = dyn_cast<RecordDecl>(FromDC);
   for (auto *From : FromDC->decls()) {
     ExpectedDecl ImportedOrErr = import(From);
-    if (!ImportedOrErr)
+    if (!ImportedOrErr) {
+      // For RecordDecls, failed import of a field will break the layout of the
+      // structure. Handle it as an error.
+      if (FromRD)
+        return ImportedOrErr.takeError();
       // Ignore the error, continue with next Decl.
       // FIXME: Handle this case somehow better.
-      consumeError(ImportedOrErr.takeError());
+      else
+        consumeError(ImportedOrErr.takeError());
+    }
+  }
+
+  // Reorder declarations in RecordDecls because they may have another
+  // order. Keeping field order is vitable because it determines structure
+  // layout.
+  // FIXME: This is an ugly fix. Unfortunately, I cannot come with better
+  // solution for this issue. We cannot defer expression import here because
+  // type import can depend on them.
+  if (!FromRD)
+    return Error::success();
+
+
+  // NOTE: Here and below, we cannot call field_begin() method and its callers
+  // on ToRD if it has an external storage. Calling field_begin() will
+  // automatically load all the fields by calling
+  // LoadFieldsFromExternalStorage().
+  auto ImportedDC = import(cast<Decl>(FromDC));
+  assert(ImportedDC);
+  auto *ToRD = cast<RecordDecl>(*ImportedDC);
+  for (auto *D : FromRD->decls()) {
+    if (isa<FieldDecl>(D) || isa<FriendDecl>(D)) {
+      Decl *ToD = Importer.GetAlreadyImportedOrNull(D);
+      assert(ToRD == ToD->getDeclContext() && ToRD->containsDecl(ToD));
+      ToRD->removeDecl(ToD);
+    }
+  }
+
+  if (!ToRD->hasExternalLexicalStorage())
+    assert(ToRD->field_empty());
+
+  for (auto *D : FromRD->decls()) {
+    if (isa<FieldDecl>(D) || isa<FriendDecl>(D)) {
+      Decl *ToD = Importer.GetAlreadyImportedOrNull(D);
+      assert(ToD);
+      assert(ToRD == ToD->getDeclContext());
+      assert(ToRD == ToD->getLexicalDeclContext());
+      if (!ToRD->hasExternalLexicalStorage())
+        assert(!ToRD->containsDecl(ToD));
+
+      ToRD->addDeclInternal(ToD);
+    }
   }
 
   return Error::success();


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D44100.189830.patch
Type: text/x-patch
Size: 3514 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20190308/a8886e0e/attachment.bin>


More information about the cfe-commits mailing list