@@ -433,6 +433,7 @@ namespace clang {
433
433
Decl *From, DeclContext *&ToDC, DeclContext *&ToLexicalDC);
434
434
Error ImportImplicitMethods(const CXXRecordDecl *From, CXXRecordDecl *To);
435
435
436
+ Error ImportFieldDeclDefinition(const FieldDecl *From, const FieldDecl *To);
436
437
Expected<CXXCastPath> ImportCastPath(CastExpr *E);
437
438
Expected<APValue> ImportAPValue(const APValue &FromValue);
438
439
@@ -1850,52 +1851,33 @@ ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) {
1850
1851
// different values in two distinct translation units.
1851
1852
ChildErrorHandlingStrategy HandleChildErrors(FromDC);
1852
1853
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.
1853
1859
Error ChildErrors = Error::success();
1854
1860
for (auto *From : FromDC->decls()) {
1861
+ if (!MightNeedReordering(From))
1862
+ continue;
1863
+
1855
1864
ExpectedDecl ImportedOrErr = import(From);
1856
1865
1857
1866
// If we are in the process of ImportDefinition(...) for a RecordDecl we
1858
1867
// want to make sure that we are also completing each FieldDecl. There
1859
1868
// are currently cases where this does not happen and this is correctness
1860
1869
// 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) {
1897
1871
HandleChildErrors.handleChildImportResult(ChildErrors,
1898
1872
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));
1899
1881
}
1900
1882
}
1901
1883
@@ -1910,7 +1892,7 @@ ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) {
1910
1892
// During the import of `a` we import first the dependencies in sequence,
1911
1893
// thus the order would be `c`, `b`, `a`. We will get the normal order by
1912
1894
// 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.
1914
1896
//
1915
1897
// Keeping field order is vital because it determines structure layout.
1916
1898
//
@@ -1922,9 +1904,6 @@ ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) {
1922
1904
// interface in LLDB is implemented by the means of the ASTImporter. However,
1923
1905
// calling an import at this point would result in an uncontrolled import, we
1924
1906
// must avoid that.
1925
- const auto *FromRD = dyn_cast<RecordDecl>(FromDC);
1926
- if (!FromRD)
1927
- return ChildErrors;
1928
1907
1929
1908
auto ToDCOrErr = Importer.ImportContext(FromDC);
1930
1909
if (!ToDCOrErr) {
@@ -1935,26 +1914,70 @@ ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) {
1935
1914
DeclContext *ToDC = *ToDCOrErr;
1936
1915
// Remove all declarations, which may be in wrong order in the
1937
1916
// 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)) {
1940
- assert(D && "DC contains a null decl");
1941
- Decl *ToD = Importer.GetAlreadyImportedOrNull(D);
1917
+ for (auto *D : FromDC->decls()) {
1918
+ if (!MightNeedReordering(D))
1919
+ continue;
1920
+
1921
+ assert(D && "DC contains a null decl");
1922
+ if (Decl *ToD = Importer.GetAlreadyImportedOrNull(D)) {
1942
1923
// Remove only the decls which we successfully imported.
1943
- if (ToD) {
1944
- assert(ToDC == ToD->getLexicalDeclContext() && ToDC->containsDecl(ToD));
1945
- // Remove the decl from its wrong place in the linked list.
1946
- ToDC->removeDecl(ToD);
1947
- // Add the decl to the end of the linked list.
1948
- // This time it will be at the proper place because the enclosing for
1949
- // loop iterates in the original (good) order of the decls.
1950
- ToDC->addDeclInternal(ToD);
1951
- }
1924
+ assert(ToDC == ToD->getLexicalDeclContext() && ToDC->containsDecl(ToD));
1925
+ // Remove the decl from its wrong place in the linked list.
1926
+ ToDC->removeDecl(ToD);
1927
+ // Add the decl to the end of the linked list.
1928
+ // This time it will be at the proper place because the enclosing for
1929
+ // loop iterates in the original (good) order of the decls.
1930
+ ToDC->addDeclInternal(ToD);
1952
1931
}
1953
1932
}
1954
1933
1934
+ // Import everything else.
1935
+ for (auto *From : FromDC->decls()) {
1936
+ if (MightNeedReordering(From))
1937
+ continue;
1938
+
1939
+ ExpectedDecl ImportedOrErr = import(From);
1940
+ if (!ImportedOrErr)
1941
+ HandleChildErrors.handleChildImportResult(ChildErrors,
1942
+ ImportedOrErr.takeError());
1943
+ }
1944
+
1955
1945
return ChildErrors;
1956
1946
}
1957
1947
1948
+ Error ASTNodeImporter::ImportFieldDeclDefinition(const FieldDecl *From,
1949
+ const FieldDecl *To) {
1950
+ RecordDecl *FromRecordDecl = nullptr;
1951
+ RecordDecl *ToRecordDecl = nullptr;
1952
+ // If we have a field that is an ArrayType we need to check if the array
1953
+ // element is a RecordDecl and if so we need to import the definition.
1954
+ QualType FromType = From->getType();
1955
+ QualType ToType = To->getType();
1956
+ if (FromType->isArrayType()) {
1957
+ // getBaseElementTypeUnsafe(...) handles multi-dimensonal arrays for us.
1958
+ FromRecordDecl = FromType->getBaseElementTypeUnsafe()->getAsRecordDecl();
1959
+ ToRecordDecl = ToType->getBaseElementTypeUnsafe()->getAsRecordDecl();
1960
+ }
1961
+
1962
+ if (!FromRecordDecl || !ToRecordDecl) {
1963
+ const RecordType *RecordFrom = FromType->getAs<RecordType>();
1964
+ const RecordType *RecordTo = ToType->getAs<RecordType>();
1965
+
1966
+ if (RecordFrom && RecordTo) {
1967
+ FromRecordDecl = RecordFrom->getDecl();
1968
+ ToRecordDecl = RecordTo->getDecl();
1969
+ }
1970
+ }
1971
+
1972
+ if (FromRecordDecl && ToRecordDecl) {
1973
+ if (FromRecordDecl->isCompleteDefinition() &&
1974
+ !ToRecordDecl->isCompleteDefinition())
1975
+ return ImportDefinition(FromRecordDecl, ToRecordDecl);
1976
+ }
1977
+
1978
+ return Error::success();
1979
+ }
1980
+
1958
1981
Error ASTNodeImporter::ImportDeclContext(
1959
1982
Decl *FromD, DeclContext *&ToDC, DeclContext *&ToLexicalDC) {
1960
1983
auto ToDCOrErr = Importer.ImportContext(FromD->getDeclContext());
0 commit comments