diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -1942,6 +1942,16 @@ ImportedOrErr.takeError()); } + // Final round to re-order everything + for (auto *D : FromDC->decls()) { + assert(D && "DC contains a null decl"); + if (Decl *ToD = Importer.GetAlreadyImportedOrNull(D); ToD && + ToDC == ToD->getLexicalDeclContext() && ToDC->containsDecl(ToD)) { + ToDC->removeDecl(ToD); + ToDC->addDeclInternal(ToD); + } + } + return ChildErrors; } diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -1462,10 +1462,10 @@ MatchVerifier{}.match(To->getTranslationUnitDecl(), Pattern)); } -AST_MATCHER_P(RecordDecl, hasFieldOrder, std::vector, Order) { +AST_MATCHER_P(RecordDecl, hasLexicalOrder, std::vector, Order) { size_t Index = 0; for (Decl *D : Node.decls()) { - if (isa(D) || isa(D)) { + if (isa(D) || isa(D) || !D->isImplicit()) { auto *ND = cast(D); if (Index == Order.size()) return false; @@ -1513,8 +1513,8 @@ Lang_CXX11, "", Lang_CXX11); MatchVerifier Verifier; - ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b"})))); - EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b"})))); + ASSERT_TRUE(Verifier.match(From, cxxRecordDecl(hasLexicalOrder({"a", "b"})))); + EXPECT_TRUE(Verifier.match(To, cxxRecordDecl(hasLexicalOrder({"a", "b"})))); } TEST_P(ASTImporterOptionSpecificTestBase, @@ -1532,11 +1532,30 @@ )s", Lang_CXX11, "", Lang_CXX11); + auto Pattern = cxxRecordDecl(hasLexicalOrder({"a", "b", "c"})); MatchVerifier Verifier; - ASSERT_TRUE( - Verifier.match(From, cxxRecordDecl(hasFieldOrder({"a", "b", "c"})))); - EXPECT_TRUE( - Verifier.match(To, cxxRecordDecl(hasFieldOrder({"a", "b", "c"})))); + ASSERT_TRUE(Verifier.match(From, Pattern)); + EXPECT_TRUE(Verifier.match(To, Pattern)); +} + +TEST_P(ASTImporterOptionSpecificTestBase, CXXRecordDeclCorrectLexicalOrder) { + Decl *From, *To; + std::tie(From, To) = getImportedDecl( + R"s( + struct declToImport { + int a = c; + void g() { h(); } + int b = 1; + void h(); + int c = 2; + }; + )s", + Lang_CXX11, "", Lang_CXX11); + + auto Pattern = cxxRecordDecl(hasLexicalOrder({"a", "g", "b", "h", "c"})); + MatchVerifier Verifier; + ASSERT_TRUE(Verifier.match(From, Pattern)); + EXPECT_TRUE(Verifier.match(To, Pattern)); } TEST_P(ASTImporterOptionSpecificTestBase, @@ -1557,11 +1576,17 @@ )s", Lang_CXX11, "", Lang_CXX11); + auto Pattern = cxxRecordDecl(hasLexicalOrder({ + "a", + "" /*anony union*/, + "" /* implicit field */, + "b" /* indirect */, + "c" /* indirect */, + "d" + })); MatchVerifier Verifier; - ASSERT_TRUE(Verifier.match( - From, cxxRecordDecl(hasFieldOrder({"a", "", "b", "c", "d"})))); - EXPECT_TRUE(Verifier.match( - To, cxxRecordDecl(hasFieldOrder({"a", "", "b", "c", "d"})))); + ASSERT_TRUE(Verifier.match(From, Pattern)); + EXPECT_TRUE(Verifier.match(To, Pattern)); } TEST_P(ASTImporterOptionSpecificTestBase, ShouldImportImplicitCXXRecordDecl) { @@ -3007,7 +3032,7 @@ " int a = 5;" "};", Lang_CXX11, "", Lang_CXX11, Verifier, - recordDecl(hasFieldOrder({"b", "a"}))); + recordDecl(hasLexicalOrder({"b", "a"}))); } const internal::VariadicDynCastAllOfMatcher