diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -7929,12 +7929,46 @@ } Expected ASTImporter::Import(const Attr *FromAttr) { - Attr *ToAttr = FromAttr->clone(ToContext); - if (auto ToRangeOrErr = Import(FromAttr->getRange())) - ToAttr->setRange(*ToRangeOrErr); - else - return ToRangeOrErr.takeError(); - + Attr *ToAttr = nullptr; + SourceRange ToRange; + if (Error Err = importInto(ToRange, FromAttr->getRange())) + return std::move(Err); + + // FIXME: Is there some kind of AttrVisitor to use here? + switch (FromAttr->getKind()) { + case attr::Aligned: { + auto *From = cast(FromAttr); + AlignedAttr *To; + if (From->isAlignmentExpr()) { + if (auto ToEOrErr = Import(From->getAlignmentExpr())) + To = AlignedAttr::Create(ToContext, true, *ToEOrErr, ToRange, + FromAttr->getSyntax(), + From->getSemanticSpelling()); + else + return ToEOrErr.takeError(); + } else { + if (auto ToTOrErr = Import(From->getAlignmentType())) + To = AlignedAttr::Create(ToContext, false, *ToTOrErr, ToRange, + FromAttr->getSyntax(), + From->getSemanticSpelling()); + else + return ToTOrErr.takeError(); + } + To->setInherited(From->isInherited()); + To->setPackExpansion(From->isPackExpansion()); + To->setImplicit(From->isImplicit()); + ToAttr = To; + break; + } + default: + // FIXME: 'clone' copies every member but some of them should be imported. + // Handle other Attrs that have parameters that should be imported. + ToAttr = FromAttr->clone(ToContext); + ToAttr->setRange(ToRange); + break; + } + assert(ToAttr && "Attribute should be created."); + return ToAttr; } diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -5887,6 +5887,39 @@ EXPECT_FALSE(ToSM.isBeforeInTranslationUnit(Location2, Location1)); } +TEST_P(ASTImporterOptionSpecificTestBase, ImportExprOfAlignmentAttr) { + // FIXME: These packed and aligned attributes could trigger an error situation + // where source location from 'From' context is referenced in 'To' context + // through evaluation of the alignof attribute. + // This happened if the 'alignof(A)' expression was not imported correctly. + Decl *FromTU = getTuDecl( + R"( + struct __attribute__((packed)) A { int __attribute__((aligned(8))) X; }; + struct alignas(alignof(A)) S {}; + )", + Lang_CXX11, "input.cc"); + auto *FromD = FirstDeclMatcher().match( + FromTU, cxxRecordDecl(hasName("S"), unless(isImplicit()))); + ASSERT_TRUE(FromD); + + auto *ToD = Import(FromD, Lang_CXX11); + ASSERT_TRUE(ToD); + + auto *FromAttr = FromD->getAttr(); + auto *ToAttr = ToD->getAttr(); + EXPECT_EQ(FromAttr->isInherited(), ToAttr->isInherited()); + EXPECT_EQ(FromAttr->isPackExpansion(), ToAttr->isPackExpansion()); + EXPECT_EQ(FromAttr->isImplicit(), ToAttr->isImplicit()); + EXPECT_TRUE(ToAttr->getAlignmentExpr()); + + auto *ToA = FirstDeclMatcher().match( + ToD->getTranslationUnitDecl(), + cxxRecordDecl(hasName("A"), unless(isImplicit()))); + // Ensure that 'struct A' was imported (through reference from attribute of + // 'S'). + EXPECT_TRUE(ToA); +} + INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest, DefaultTestValuesForRunOptions, );