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 @@ -7947,12 +7947,47 @@ } 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; + auto CreateAlign = [&](bool IsAlignmentExpr, void *Alignment) { + return AlignedAttr::Create(ToContext, IsAlignmentExpr, Alignment, ToRange, + From->getSyntax(), + From->getSemanticSpelling()); + }; + if (From->isAlignmentExpr()) { + if (auto ToEOrErr = Import(From->getAlignmentExpr())) + To = CreateAlign(true, *ToEOrErr); + else + return ToEOrErr.takeError(); + } else { + if (auto ToTOrErr = Import(From->getAlignmentType())) + To = CreateAlign(false, *ToTOrErr); + 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,41 @@ EXPECT_FALSE(ToSM.isBeforeInTranslationUnit(Location2, Location1)); } +TEST_P(ASTImporterOptionSpecificTestBase, ImportExprOfAlignmentAttr) { + // Test if import of these packed and aligned attributes does not trigger an + // error situation where source location from 'From' context is referenced in + // 'To' context through evaluation of the alignof attribute. + // This happens if the 'alignof(A)' expression is 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_EQ(FromAttr->getSyntax(), ToAttr->getSyntax()); + EXPECT_EQ(FromAttr->getSemanticSpelling(), ToAttr->getSemanticSpelling()); + 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, );