@@ -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,25 +1904,24 @@ 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) {
1931
1910
consumeError (std::move (ChildErrors));
1932
1911
return ToDCOrErr.takeError ();
1933
1912
}
1934
1913
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
+
1940
1922
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.
1944
1925
assert (ToDC == ToD->getLexicalDeclContext () && ToDC->containsDecl (ToD));
1945
1926
// Remove the decl from its wrong place in the linked list.
1946
1927
ToDC->removeDecl (ToD);
@@ -1952,9 +1933,53 @@ ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) {
1952
1933
}
1953
1934
}
1954
1935
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
+
1955
1947
return ChildErrors;
1956
1948
}
1957
1949
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
+
1958
1983
Error ASTNodeImporter::ImportDeclContext (
1959
1984
Decl *FromD, DeclContext *&ToDC, DeclContext *&ToLexicalDC) {
1960
1985
auto ToDCOrErr = Importer.ImportContext (FromD->getDeclContext ());
0 commit comments