Index: lib/AST/ASTImporter.cpp =================================================================== --- lib/AST/ASTImporter.cpp +++ lib/AST/ASTImporter.cpp @@ -1015,6 +1015,34 @@ for (auto *From : FromDC->decls()) Importer.Import(From); + + // 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. + const RecordDecl *FromRD = dyn_cast(FromDC); + if (!FromRD) + return; + + RecordDecl *ToRD = cast(Importer.Import(cast(FromDC))); + + for (auto *FromField : FromRD->fields()) { + Decl *ToField = Importer.GetAlreadyImportedOrNull(FromField); + assert(ToRD == ToField->getDeclContext() && ToRD->containsDecl(ToField)); + ToRD->removeDecl(ToField); + } + + assert(ToRD->field_empty()); + + for (auto *FromField : FromRD->fields()) { + Decl *ToField = Importer.GetAlreadyImportedOrNull(FromField); + assert(ToRD == ToField->getDeclContext()); + assert(ToRD == ToField->getLexicalDeclContext()); + assert(!ToRD->containsDecl(ToField)); + ToRD->addDeclInternal(ToField); + } } bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, Index: unittests/AST/ASTImporterTest.cpp =================================================================== --- unittests/AST/ASTImporterTest.cpp +++ unittests/AST/ASTImporterTest.cpp @@ -1019,5 +1019,28 @@ "main.c", enumDecl(), VerificationMatcher); } +AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector, Order) { + size_t Index = 0; + for (FieldDecl *Field : Node.fields()) { + if (Index == Order.size()) + return false; + if (Field->getName() != Order[Index]) + return false; + ++Index; + } + return Index == Order.size(); +} + +TEST(ImportDecl, ImportFieldOrder) { + MatchVerifier 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