Index: include/clang/AST/ASTImporter.h =================================================================== --- include/clang/AST/ASTImporter.h +++ include/clang/AST/ASTImporter.h @@ -41,6 +41,7 @@ class Stmt; class TagDecl; class TypeSourceInfo; +class Attr; /// \brief Imports selected nodes from one AST context into another context, /// merging AST nodes where appropriate. @@ -130,6 +131,12 @@ /// context, or NULL if an error occurred. TypeSourceInfo *Import(TypeSourceInfo *FromTSI); + /// \brief Import the given attribute from the "from" context into the + /// "to" context. + /// + /// \returns the equivalent attribute in the "to" context. + Attr *Import(const Attr *FromAttr); + /// \brief Import the given declaration from the "from" context into the /// "to" context. /// Index: lib/AST/ASTImporter.cpp =================================================================== --- lib/AST/ASTImporter.cpp +++ lib/AST/ASTImporter.cpp @@ -2646,8 +2646,8 @@ Importer.getToContext(), DC, Loc, Name.getAsIdentifierInfo(), T, {NamedChain, D->getChainingSize()}); - for (const auto *Attr : D->attrs()) - ToIndirectField->addAttr(Attr->clone(Importer.getToContext())); + for (const auto *A : D->attrs()) + ToIndirectField->addAttr(Importer.Import(A)); ToIndirectField->setAccess(D->getAccess()); ToIndirectField->setLexicalDeclContext(LexicalDC); @@ -4721,15 +4721,8 @@ SourceLocation ToAttrLoc = Importer.Import(S->getAttrLoc()); ArrayRef FromAttrs(S->getAttrs()); SmallVector ToAttrs(FromAttrs.size()); - ASTContext &_ToContext = Importer.getToContext(); - std::transform(FromAttrs.begin(), FromAttrs.end(), ToAttrs.begin(), - [&_ToContext](const Attr *A) -> const Attr * { - return A->clone(_ToContext); - }); - for (const auto *ToA : ToAttrs) { - if (!ToA) - return nullptr; - } + if (ImportArrayChecked(FromAttrs, ToAttrs.begin())) + return nullptr; Stmt *ToSubStmt = Importer.Import(S->getSubStmt()); if (!ToSubStmt && S->getSubStmt()) return nullptr; @@ -6544,6 +6537,12 @@ Import(FromTSI->getTypeLoc().getLocStart())); } +Attr *ASTImporter::Import(const Attr *FromAttr) { + Attr *ToAttr = FromAttr->clone(ToContext); + ToAttr->setRange(Import(FromAttr->getRange())); + return ToAttr; +} + Decl *ASTImporter::GetAlreadyImportedOrNull(Decl *FromD) { llvm::DenseMap::iterator Pos = ImportedDecls.find(FromD); if (Pos != ImportedDecls.end()) { @@ -7199,8 +7198,8 @@ Decl *ASTImporter::Imported(Decl *From, Decl *To) { if (From->hasAttrs()) { - for (auto *FromAttr : From->getAttrs()) - To->addAttr(FromAttr->clone(To->getASTContext())); + for (const auto *FromAttr : From->getAttrs()) + To->addAttr(Import(FromAttr)); } if (From->isUsed()) { To->setIsUsed(); Index: test/Import/attr/Inputs/S.cpp =================================================================== --- test/Import/attr/Inputs/S.cpp +++ test/Import/attr/Inputs/S.cpp @@ -0,0 +1,13 @@ +extern void f() __attribute__((const)); + +struct S { + struct { + int a __attribute__((packed)); + }; +}; + +void stmt() { +#pragma unroll + for (;;) + ; +} Index: test/Import/attr/test.cpp =================================================================== --- test/Import/attr/test.cpp +++ test/Import/attr/test.cpp @@ -0,0 +1,26 @@ +// RUN: clang-import-test -dump-ast -import %S/Inputs/S.cpp -expression %s | FileCheck %s +// CHECK: FunctionDecl +// CHECK-SAME: S.cpp:1:1, col:13 +// CHECK-NEXT: ConstAttr +// CHECK-SAME: col:32 + +// CHECK: IndirectFieldDecl +// CHECK-NEXT: Field +// CHECK-NEXT: Field +// CHECK-NEXT: PackedAttr +// CHECK-SAME: col:26 + +// CHECK: AttributedStmt +// CHECK-NEXT: LoopHintAttr +// CHECK-SAME: line:10:9 + +extern void f() __attribute__((const)); + +struct S; + +void stmt(); + +void expr() { + f(); + struct S s; +}