Skip to content

Commit 9d0b55f

Browse files
committed
[clang][ASTImporter] Fix import of typedef with unnamed structures
Fix crash in ASTImporter related to import of unnamed structures and typedefs to these maybe with pointer. There was a series of problems exposed by https://reviews.llvm.org/D133468 (commit 69a6417) in the ASTImporter breaking cross-translation unit analysis. This change fixes one of the problems exposed by that change for importing unnamed structures. The problem was discovered when running clang static analysis on open source projects using cross-translation unit analysis. Simple test command. Produces crash without change, passes all tests with change. ``` ninja ASTTests && ./tools/clang/unittests/AST/ASTTests --gtest_filter="*/*ImportAnonymousStruct/0" ``` Formatted crash stack: ``` ASTTests: <root>/clang/lib/AST/ASTContext.cpp:4787: clang::QualType clang::ASTContext::getTypedefType(const clang::TypedefNameDecl*, clang::QualType) const: Assertion `hasSameType(Decl->getUnderlyingType(), Underlying)' failed. ... rust-lang#9 <addr> clang::ASTContext::getTypedefType(clang::TypedefNameDecl const*, clang::QualType) const <root>/clang/lib/AST/ASTContext.cpp:4789:26 <root>/clang/lib/AST/ASTImporter.cpp:1374:71 <root>/tools/clang/include/clang/AST/TypeNodes.inc:75:1 <root>/clang/lib/AST/ASTImporter.cpp:8663:8 ``` Reviewed By: donat.nagy Differential Revision: https://reviews.llvm.org/D145868
1 parent c1f7636 commit 9d0b55f

File tree

2 files changed

+69
-2
lines changed

2 files changed

+69
-2
lines changed

clang/lib/AST/ASTImporter.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,12 +1365,16 @@ ExpectedType ASTNodeImporter::VisitTypedefType(const TypedefType *T) {
13651365
Expected<TypedefNameDecl *> ToDeclOrErr = import(T->getDecl());
13661366
if (!ToDeclOrErr)
13671367
return ToDeclOrErr.takeError();
1368+
1369+
TypedefNameDecl *ToDecl = *ToDeclOrErr;
1370+
if (ToDecl->getTypeForDecl())
1371+
return QualType(ToDecl->getTypeForDecl(), 0);
1372+
13681373
ExpectedType ToUnderlyingTypeOrErr = import(T->desugar());
13691374
if (!ToUnderlyingTypeOrErr)
13701375
return ToUnderlyingTypeOrErr.takeError();
13711376

1372-
return Importer.getToContext().getTypedefType(*ToDeclOrErr,
1373-
*ToUnderlyingTypeOrErr);
1377+
return Importer.getToContext().getTypedefType(ToDecl, *ToUnderlyingTypeOrErr);
13741378
}
13751379

13761380
ExpectedType ASTNodeImporter::VisitTypeOfExprType(const TypeOfExprType *T) {

clang/unittests/AST/ASTImporterTest.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8576,6 +8576,69 @@ TEST_P(ASTImporterOptionSpecificTestBase, ImportTwoTypedefsToUnnamedRecord) {
85768576
Typedef2->getUnderlyingType().getTypePtr());
85778577
}
85788578

8579+
TEST_P(ASTImporterOptionSpecificTestBase,
8580+
ImportExistingTypedefToUnnamedRecordPtr) {
8581+
const char *Code =
8582+
R"(
8583+
typedef const struct { int fff; } * const T;
8584+
extern T x;
8585+
)";
8586+
Decl *ToTU = getToTuDecl(Code, Lang_C99);
8587+
Decl *FromTU = getTuDecl(Code, Lang_C99);
8588+
8589+
auto *FromX =
8590+
FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("x")));
8591+
auto *ToX = Import(FromX, Lang_C99);
8592+
EXPECT_TRUE(ToX);
8593+
8594+
auto *Typedef1 =
8595+
FirstDeclMatcher<TypedefDecl>().match(ToTU, typedefDecl(hasName("T")));
8596+
auto *Typedef2 =
8597+
LastDeclMatcher<TypedefDecl>().match(ToTU, typedefDecl(hasName("T")));
8598+
// FIXME: These should be imported separately, like in the test above.
8599+
// Or: In the test above these should be merged too.
8600+
EXPECT_EQ(Typedef1, Typedef2);
8601+
8602+
auto *FromR = FirstDeclMatcher<RecordDecl>().match(
8603+
FromTU, recordDecl(hasDescendant(fieldDecl(hasName("fff")))));
8604+
auto *ToRExisting = FirstDeclMatcher<RecordDecl>().match(
8605+
ToTU, recordDecl(hasDescendant(fieldDecl(hasName("fff")))));
8606+
ASSERT_TRUE(FromR);
8607+
auto *ToRImported = Import(FromR, Lang_C99);
8608+
// FIXME: If typedefs are not imported separately, do not import ToRImported
8609+
// separately.
8610+
EXPECT_NE(ToRExisting, ToRImported);
8611+
}
8612+
8613+
TEST_P(ASTImporterOptionSpecificTestBase,
8614+
ImportTypedefWithDifferentUnderlyingType) {
8615+
const char *Code =
8616+
R"(
8617+
using X1 = int;
8618+
using Y1 = int;
8619+
8620+
using RPB1 = X1*;
8621+
typedef RPB1 RPX1;
8622+
using RPB1 = Y1*; // redeclared
8623+
typedef RPB1 RPY1;
8624+
8625+
auto X = 0 ? (RPX1){} : (RPY1){};
8626+
)";
8627+
Decl *ToTU = getToTuDecl("", Lang_CXX11);
8628+
Decl *FromTU = getTuDecl(Code, Lang_CXX11);
8629+
8630+
auto *FromX =
8631+
FirstDeclMatcher<VarDecl>().match(FromTU, varDecl(hasName("X")));
8632+
8633+
auto *FromXType = FromX->getType()->getAs<TypedefType>();
8634+
EXPECT_FALSE(FromXType->typeMatchesDecl());
8635+
8636+
auto *ToX = Import(FromX, Lang_CXX11);
8637+
auto *ToXType = ToX->getType()->getAs<TypedefType>();
8638+
// FIXME: This should be false.
8639+
EXPECT_TRUE(ToXType->typeMatchesDecl());
8640+
}
8641+
85798642
INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ASTImporterLookupTableTest,
85808643
DefaultTestValuesForRunOptions);
85818644

0 commit comments

Comments
 (0)