From: Balázs Kéri <1.int32@gmail.com> Date: Thu, 13 Apr 2023 06:53:46 +0000 (+0200) Subject: [clang][ASTImporter] Fix import of typedef with unnamed structures X-Git-Tag: upstream/17.0.6~11821 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9d0b55f0e4ca55d04ee8abfdf021913ea3c30082;p=platform%2Fupstream%2Fllvm.git [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 69a6417406a1b0316a1fa6aeb63339d0e1d2abbd) 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: /clang/lib/AST/ASTContext.cpp:4787: clang::QualType clang::ASTContext::getTypedefType(const clang::TypedefNameDecl*, clang::QualType) const: Assertion `hasSameType(Decl->getUnderlyingType(), Underlying)' failed. ... #9 clang::ASTContext::getTypedefType(clang::TypedefNameDecl const*, clang::QualType) const /clang/lib/AST/ASTContext.cpp:4789:26 /clang/lib/AST/ASTImporter.cpp:1374:71 /tools/clang/include/clang/AST/TypeNodes.inc:75:1 /clang/lib/AST/ASTImporter.cpp:8663:8 ``` Reviewed By: donat.nagy Differential Revision: https://reviews.llvm.org/D145868 --- diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 337c14a..320c302 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -1365,12 +1365,16 @@ ExpectedType ASTNodeImporter::VisitTypedefType(const TypedefType *T) { Expected ToDeclOrErr = import(T->getDecl()); if (!ToDeclOrErr) return ToDeclOrErr.takeError(); + + TypedefNameDecl *ToDecl = *ToDeclOrErr; + if (ToDecl->getTypeForDecl()) + return QualType(ToDecl->getTypeForDecl(), 0); + ExpectedType ToUnderlyingTypeOrErr = import(T->desugar()); if (!ToUnderlyingTypeOrErr) return ToUnderlyingTypeOrErr.takeError(); - return Importer.getToContext().getTypedefType(*ToDeclOrErr, - *ToUnderlyingTypeOrErr); + return Importer.getToContext().getTypedefType(ToDecl, *ToUnderlyingTypeOrErr); } ExpectedType ASTNodeImporter::VisitTypeOfExprType(const TypeOfExprType *T) { diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index ebdb81b..b90a18d 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -8576,6 +8576,69 @@ TEST_P(ASTImporterOptionSpecificTestBase, ImportTwoTypedefsToUnnamedRecord) { Typedef2->getUnderlyingType().getTypePtr()); } +TEST_P(ASTImporterOptionSpecificTestBase, + ImportExistingTypedefToUnnamedRecordPtr) { + const char *Code = + R"( + typedef const struct { int fff; } * const T; + extern T x; + )"; + Decl *ToTU = getToTuDecl(Code, Lang_C99); + Decl *FromTU = getTuDecl(Code, Lang_C99); + + auto *FromX = + FirstDeclMatcher().match(FromTU, varDecl(hasName("x"))); + auto *ToX = Import(FromX, Lang_C99); + EXPECT_TRUE(ToX); + + auto *Typedef1 = + FirstDeclMatcher().match(ToTU, typedefDecl(hasName("T"))); + auto *Typedef2 = + LastDeclMatcher().match(ToTU, typedefDecl(hasName("T"))); + // FIXME: These should be imported separately, like in the test above. + // Or: In the test above these should be merged too. + EXPECT_EQ(Typedef1, Typedef2); + + auto *FromR = FirstDeclMatcher().match( + FromTU, recordDecl(hasDescendant(fieldDecl(hasName("fff"))))); + auto *ToRExisting = FirstDeclMatcher().match( + ToTU, recordDecl(hasDescendant(fieldDecl(hasName("fff"))))); + ASSERT_TRUE(FromR); + auto *ToRImported = Import(FromR, Lang_C99); + // FIXME: If typedefs are not imported separately, do not import ToRImported + // separately. + EXPECT_NE(ToRExisting, ToRImported); +} + +TEST_P(ASTImporterOptionSpecificTestBase, + ImportTypedefWithDifferentUnderlyingType) { + const char *Code = + R"( + using X1 = int; + using Y1 = int; + + using RPB1 = X1*; + typedef RPB1 RPX1; + using RPB1 = Y1*; // redeclared + typedef RPB1 RPY1; + + auto X = 0 ? (RPX1){} : (RPY1){}; + )"; + Decl *ToTU = getToTuDecl("", Lang_CXX11); + Decl *FromTU = getTuDecl(Code, Lang_CXX11); + + auto *FromX = + FirstDeclMatcher().match(FromTU, varDecl(hasName("X"))); + + auto *FromXType = FromX->getType()->getAs(); + EXPECT_FALSE(FromXType->typeMatchesDecl()); + + auto *ToX = Import(FromX, Lang_CXX11); + auto *ToXType = ToX->getType()->getAs(); + // FIXME: This should be false. + EXPECT_TRUE(ToXType->typeMatchesDecl()); +} + INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ASTImporterLookupTableTest, DefaultTestValuesForRunOptions);