Skip to content

Commit 83028ad

Browse files
committed
[clang][AST][ASTImporter] Set record to complete during import of its members.
At import of a member it may require that the record is already set to complete. (For example 'computeDependence' at create of some Expr nodes.) The record at this time may not be completely imported, the result of layout calculations can be incorrect, but at least no crash occurs this way. A good solution would be if fields of every encountered record are imported before other members of all records. This is much more difficult to implement. Differential Revision: https://reviews.llvm.org/D116155
1 parent e59d6dc commit 83028ad

File tree

2 files changed

+63
-2
lines changed

2 files changed

+63
-2
lines changed

clang/lib/AST/ASTImporter.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2012,6 +2012,14 @@ Error ASTNodeImporter::ImportDefinition(
20122012
}
20132013

20142014
To->startDefinition();
2015+
// Set the definition to complete even if it is really not complete during
2016+
// import. Some AST constructs (expressions) require the record layout
2017+
// to be calculated (see 'clang::computeDependence') at the time they are
2018+
// constructed. Import of such AST node is possible during import of the
2019+
// same record, there is no way to have a completely defined record (all
2020+
// fields imported) at that time without multiple AST import passes.
2021+
if (!Importer.isMinimalImport())
2022+
To->setCompleteDefinition(true);
20152023
// Complete the definition even if error is returned.
20162024
// The RecordDecl may be already part of the AST so it is better to
20172025
// have it in complete state even if something is wrong with it.
@@ -2076,9 +2084,10 @@ Error ASTNodeImporter::ImportDefinition(
20762084
ToCXX->setBases(Bases.data(), Bases.size());
20772085
}
20782086

2079-
if (shouldForceImportDeclContext(Kind))
2087+
if (shouldForceImportDeclContext(Kind)) {
20802088
if (Error Err = ImportDeclContext(From, /*ForceImport=*/true))
20812089
return Err;
2090+
}
20822091

20832092
return Error::success();
20842093
}

clang/unittests/AST/ASTImporterTest.cpp

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6809,7 +6809,8 @@ struct ImportWithExternalSource : ASTImporterOptionSpecificTestBase {
68096809
bool MinimalImport,
68106810
const std::shared_ptr<ASTImporterSharedState> &SharedState) {
68116811
return new ASTImporter(ToContext, ToFileManager, FromContext,
6812-
FromFileManager, MinimalImport,
6812+
// Use minimal import for these tests.
6813+
FromFileManager, /*MinimalImport=*/true,
68136814
// We use the regular lookup.
68146815
/*SharedState=*/nullptr);
68156816
};
@@ -7475,6 +7476,57 @@ TEST_P(ASTImporterOptionSpecificTestBase, ImportDeductionGuideDifferentOrder) {
74757476
ToDGOther);
74767477
}
74777478

7479+
TEST_P(ASTImporterOptionSpecificTestBase,
7480+
ImportRecordWithLayoutRequestingExpr) {
7481+
TranslationUnitDecl *FromTU = getTuDecl(
7482+
R"(
7483+
struct A {
7484+
int idx;
7485+
static void foo(A x) {
7486+
(void)&"text"[x.idx];
7487+
}
7488+
};
7489+
)",
7490+
Lang_CXX11);
7491+
7492+
auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
7493+
FromTU, cxxRecordDecl(hasName("A")));
7494+
7495+
// Test that during import of 'foo' the record layout can be obtained without
7496+
// crash.
7497+
auto *ToA = Import(FromA, Lang_CXX11);
7498+
EXPECT_TRUE(ToA);
7499+
EXPECT_TRUE(ToA->isCompleteDefinition());
7500+
}
7501+
7502+
TEST_P(ASTImporterOptionSpecificTestBase,
7503+
ImportRecordWithLayoutRequestingExprDifferentRecord) {
7504+
TranslationUnitDecl *FromTU = getTuDecl(
7505+
R"(
7506+
struct B;
7507+
struct A {
7508+
int idx;
7509+
B *b;
7510+
};
7511+
struct B {
7512+
static void foo(A x) {
7513+
(void)&"text"[x.idx];
7514+
}
7515+
};
7516+
)",
7517+
Lang_CXX11);
7518+
7519+
auto *FromA = FirstDeclMatcher<CXXRecordDecl>().match(
7520+
FromTU, cxxRecordDecl(hasName("A")));
7521+
7522+
// Test that during import of 'foo' the record layout (of 'A') can be obtained
7523+
// without crash. It is not possible to have all of the fields of 'A' imported
7524+
// at that time (without big code changes).
7525+
auto *ToA = Import(FromA, Lang_CXX11);
7526+
EXPECT_TRUE(ToA);
7527+
EXPECT_TRUE(ToA->isCompleteDefinition());
7528+
}
7529+
74787530
INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ASTImporterLookupTableTest,
74797531
DefaultTestValuesForRunOptions);
74807532

0 commit comments

Comments
 (0)