@@ -433,6 +433,7 @@ namespace clang {
433433 Decl *From, DeclContext *&ToDC, DeclContext *&ToLexicalDC);
434434 Error ImportImplicitMethods (const CXXRecordDecl *From, CXXRecordDecl *To);
435435
436+ Error ImportFieldDeclDefinition (const FieldDecl *From, const FieldDecl *To);
436437 Expected<CXXCastPath> ImportCastPath (CastExpr *E);
437438 Expected<APValue> ImportAPValue (const APValue &FromValue);
438439
@@ -1850,52 +1851,33 @@ ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) {
18501851 // different values in two distinct translation units.
18511852 ChildErrorHandlingStrategy HandleChildErrors (FromDC);
18521853
1854+ auto MightNeedReordering = [](const Decl *D) {
1855+ return isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D) || isa<FriendDecl>(D);
1856+ };
1857+
1858+ // Import everything that might need reordering first.
18531859 Error ChildErrors = Error::success ();
18541860 for (auto *From : FromDC->decls ()) {
1861+ if (!MightNeedReordering (From))
1862+ continue ;
1863+
18551864 ExpectedDecl ImportedOrErr = import (From);
18561865
18571866 // If we are in the process of ImportDefinition(...) for a RecordDecl we
18581867 // want to make sure that we are also completing each FieldDecl. There
18591868 // are currently cases where this does not happen and this is correctness
18601869 // fix since operations such as code generation will expect this to be so.
1861- if (ImportedOrErr) {
1862- FieldDecl *FieldFrom = dyn_cast_or_null<FieldDecl>(From);
1863- Decl *ImportedDecl = *ImportedOrErr;
1864- FieldDecl *FieldTo = dyn_cast_or_null<FieldDecl>(ImportedDecl);
1865- if (FieldFrom && FieldTo) {
1866- RecordDecl *FromRecordDecl = nullptr ;
1867- RecordDecl *ToRecordDecl = nullptr ;
1868- // If we have a field that is an ArrayType we need to check if the array
1869- // element is a RecordDecl and if so we need to import the definition.
1870- if (FieldFrom->getType ()->isArrayType ()) {
1871- // getBaseElementTypeUnsafe(...) handles multi-dimensonal arrays for us.
1872- FromRecordDecl = FieldFrom->getType ()->getBaseElementTypeUnsafe ()->getAsRecordDecl ();
1873- ToRecordDecl = FieldTo->getType ()->getBaseElementTypeUnsafe ()->getAsRecordDecl ();
1874- }
1875-
1876- if (!FromRecordDecl || !ToRecordDecl) {
1877- const RecordType *RecordFrom =
1878- FieldFrom->getType ()->getAs <RecordType>();
1879- const RecordType *RecordTo = FieldTo->getType ()->getAs <RecordType>();
1880-
1881- if (RecordFrom && RecordTo) {
1882- FromRecordDecl = RecordFrom->getDecl ();
1883- ToRecordDecl = RecordTo->getDecl ();
1884- }
1885- }
1886-
1887- if (FromRecordDecl && ToRecordDecl) {
1888- if (FromRecordDecl->isCompleteDefinition () &&
1889- !ToRecordDecl->isCompleteDefinition ()) {
1890- Error Err = ImportDefinition (FromRecordDecl, ToRecordDecl);
1891- HandleChildErrors.handleChildImportResult (ChildErrors,
1892- std::move (Err));
1893- }
1894- }
1895- }
1896- } else {
1870+ if (!ImportedOrErr) {
18971871 HandleChildErrors.handleChildImportResult (ChildErrors,
18981872 ImportedOrErr.takeError ());
1873+ continue ;
1874+ }
1875+ FieldDecl *FieldFrom = dyn_cast_or_null<FieldDecl>(From);
1876+ Decl *ImportedDecl = *ImportedOrErr;
1877+ FieldDecl *FieldTo = dyn_cast_or_null<FieldDecl>(ImportedDecl);
1878+ if (FieldFrom && FieldTo) {
1879+ Error Err = ImportFieldDeclDefinition (FieldFrom, FieldTo);
1880+ HandleChildErrors.handleChildImportResult (ChildErrors, std::move (Err));
18991881 }
19001882 }
19011883
@@ -1910,7 +1892,7 @@ ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) {
19101892 // During the import of `a` we import first the dependencies in sequence,
19111893 // thus the order would be `c`, `b`, `a`. We will get the normal order by
19121894 // first removing the already imported members and then adding them in the
1913- // order as they apper in the "from" context.
1895+ // order as they appear in the "from" context.
19141896 //
19151897 // Keeping field order is vital because it determines structure layout.
19161898 //
@@ -1922,25 +1904,24 @@ ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) {
19221904 // interface in LLDB is implemented by the means of the ASTImporter. However,
19231905 // calling an import at this point would result in an uncontrolled import, we
19241906 // must avoid that.
1925- const auto *FromRD = dyn_cast<RecordDecl>(FromDC);
1926- if (!FromRD)
1927- return ChildErrors;
19281907
19291908 auto ToDCOrErr = Importer.ImportContext (FromDC);
19301909 if (!ToDCOrErr) {
19311910 consumeError (std::move (ChildErrors));
19321911 return ToDCOrErr.takeError ();
19331912 }
19341913
1935- DeclContext *ToDC = *ToDCOrErr;
1936- // Remove all declarations, which may be in wrong order in the
1937- // lexical DeclContext and then add them in the proper order.
1938- for (auto *D : FromRD->decls ()) {
1939- if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D) || isa<FriendDecl>(D)) {
1914+ if (const auto *FromRD = dyn_cast<RecordDecl>(FromDC)) {
1915+ DeclContext *ToDC = *ToDCOrErr;
1916+ // Remove all declarations, which may be in wrong order in the
1917+ // lexical DeclContext and then add them in the proper order.
1918+ for (auto *D : FromRD->decls ()) {
1919+ if (!MightNeedReordering (D))
1920+ continue ;
1921+
19401922 assert (D && " DC contains a null decl" );
1941- Decl *ToD = Importer.GetAlreadyImportedOrNull (D);
1942- // Remove only the decls which we successfully imported.
1943- if (ToD) {
1923+ if (Decl *ToD = Importer.GetAlreadyImportedOrNull (D)) {
1924+ // Remove only the decls which we successfully imported.
19441925 assert (ToDC == ToD->getLexicalDeclContext () && ToDC->containsDecl (ToD));
19451926 // Remove the decl from its wrong place in the linked list.
19461927 ToDC->removeDecl (ToD);
@@ -1952,9 +1933,53 @@ ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) {
19521933 }
19531934 }
19541935
1936+ // Import everything else.
1937+ for (auto *From : FromDC->decls ()) {
1938+ if (MightNeedReordering (From))
1939+ continue ;
1940+
1941+ ExpectedDecl ImportedOrErr = import (From);
1942+ if (!ImportedOrErr)
1943+ HandleChildErrors.handleChildImportResult (ChildErrors,
1944+ ImportedOrErr.takeError ());
1945+ }
1946+
19551947 return ChildErrors;
19561948}
19571949
1950+ Error ASTNodeImporter::ImportFieldDeclDefinition (const FieldDecl *From,
1951+ const FieldDecl *To) {
1952+ RecordDecl *FromRecordDecl = nullptr ;
1953+ RecordDecl *ToRecordDecl = nullptr ;
1954+ // If we have a field that is an ArrayType we need to check if the array
1955+ // element is a RecordDecl and if so we need to import the definition.
1956+ QualType FromType = From->getType ();
1957+ QualType ToType = To->getType ();
1958+ if (FromType->isArrayType ()) {
1959+ // getBaseElementTypeUnsafe(...) handles multi-dimensonal arrays for us.
1960+ FromRecordDecl = FromType->getBaseElementTypeUnsafe ()->getAsRecordDecl ();
1961+ ToRecordDecl = ToType->getBaseElementTypeUnsafe ()->getAsRecordDecl ();
1962+ }
1963+
1964+ if (!FromRecordDecl || !ToRecordDecl) {
1965+ const RecordType *RecordFrom = FromType->getAs <RecordType>();
1966+ const RecordType *RecordTo = ToType->getAs <RecordType>();
1967+
1968+ if (RecordFrom && RecordTo) {
1969+ FromRecordDecl = RecordFrom->getDecl ();
1970+ ToRecordDecl = RecordTo->getDecl ();
1971+ }
1972+ }
1973+
1974+ if (FromRecordDecl && ToRecordDecl) {
1975+ if (FromRecordDecl->isCompleteDefinition () &&
1976+ !ToRecordDecl->isCompleteDefinition ())
1977+ return ImportDefinition (FromRecordDecl, ToRecordDecl);
1978+ }
1979+
1980+ return Error::success ();
1981+ }
1982+
19581983Error ASTNodeImporter::ImportDeclContext (
19591984 Decl *FromD, DeclContext *&ToDC, DeclContext *&ToLexicalDC) {
19601985 auto ToDCOrErr = Importer.ImportContext (FromD->getDeclContext ());
0 commit comments