Commit b17f2920 authored by Balázs Kéri's avatar Balázs Kéri
Browse files

[ASTImporter] Improved import of AlignedAttr.

Summary:
It is not enough to clone the attributes at import.
They can contain reference to objects that should be imported.
This work is done now for AlignedAttr.

Reviewers: martong, a.sidorin, shafik

Reviewed By: shafik

Subscribers: rnkovacs, dkrupp, Szelethus, gamesh411, teemperor, martong, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D75048
parent 48fad110
Loading
Loading
Loading
Loading
+41 −6
Original line number Diff line number Diff line
@@ -7947,11 +7947,46 @@ Expected<TypeSourceInfo *> ASTImporter::Import(TypeSourceInfo *FromTSI) {
}

Expected<Attr *> ASTImporter::Import(const Attr *FromAttr) {
  Attr *ToAttr = FromAttr->clone(ToContext);
  if (auto ToRangeOrErr = Import(FromAttr->getRange()))
    ToAttr->setRange(*ToRangeOrErr);
  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<AlignedAttr>(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 ToRangeOrErr.takeError();
        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;
}
+35 −0
Original line number Diff line number Diff line
@@ -5887,6 +5887,41 @@ TEST_P(ImportSourceLocations, PreserveFileIDTreeStructure) {
  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<CXXRecordDecl>().match(
      FromTU, cxxRecordDecl(hasName("S"), unless(isImplicit())));
  ASSERT_TRUE(FromD);

  auto *ToD = Import(FromD, Lang_CXX11);
  ASSERT_TRUE(ToD);

  auto *FromAttr = FromD->getAttr<AlignedAttr>();
  auto *ToAttr = ToD->getAttr<AlignedAttr>();
  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<CXXRecordDecl>().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, );