https://github.com/VitaNuo updated https://github.com/llvm/llvm-project/pull/122726
>From b61110999596363bafdc94904356840febfcfaa5 Mon Sep 17 00:00:00 2001 From: Viktoriia Bakalova <bakal...@google.com> Date: Tue, 14 Jan 2025 14:00:48 +0100 Subject: [PATCH 1/4] [WIP][Modules] Delay deserialization of preferred_name attribute at record level. --- clang/include/clang/Serialization/ASTReader.h | 18 ++++ .../clang/Serialization/ASTRecordReader.h | 10 ++ clang/lib/Serialization/ASTReader.cpp | 5 + clang/lib/Serialization/ASTReaderDecl.cpp | 91 ++++++++++++++++++- clang/lib/Serialization/ASTWriter.cpp | 19 +++- clang/test/Modules/preferred_name.cppm | 12 ++- 6 files changed, 142 insertions(+), 13 deletions(-) diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 9f978762a6fb6b..4fd51eabe701ba 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -1205,6 +1205,23 @@ class ASTReader /// been completed. std::deque<PendingDeclContextInfo> PendingDeclContextInfos; + /// Deserialization of some attributes must be deferred since they refer + /// to themselves in their type (e.g., preferred_name attribute refers to the + /// typedef that refers back to the template specialization of the template + /// that the attribute is attached to). + /// More attributes that store TypeSourceInfo might be potentially affected, + /// see https://github.com/llvm/llvm-project/issues/56490 for details. + struct DeferredAttribute { + uint64_t RecordIdx; + // Decl to attach a deferred attribute to. + Decl *ParentDecl; + }; + + /// The collection of Decls that have been loaded but some of their attributes + /// have been deferred, paired with the index inside the record pointing + /// at the skipped attribute. + SmallVector<DeferredAttribute> PendingDeferredAttributes; + template <typename DeclTy> using DuplicateObjCDecls = std::pair<DeclTy *, DeclTy *>; @@ -1551,6 +1568,7 @@ class ASTReader void loadPendingDeclChain(Decl *D, uint64_t LocalOffset); void loadObjCCategories(GlobalDeclID ID, ObjCInterfaceDecl *D, unsigned PreviousGeneration = 0); + void loadDeferredAttribute(const DeferredAttribute &DA); RecordLocation getLocalBitOffset(uint64_t GlobalOffset); uint64_t getGlobalBitOffset(ModuleFile &M, uint64_t LocalOffset); diff --git a/clang/include/clang/Serialization/ASTRecordReader.h b/clang/include/clang/Serialization/ASTRecordReader.h index 2561418b78ca7f..b1572ecef9028c 100644 --- a/clang/include/clang/Serialization/ASTRecordReader.h +++ b/clang/include/clang/Serialization/ASTRecordReader.h @@ -337,6 +337,12 @@ class ASTRecordReader /// Reads attributes from the current stream position, advancing Idx. void readAttributes(AttrVec &Attrs); + /// Reads one attribute from the current stream position, advancing Idx. + Attr *readOrDeferAttr(Decl *D); + + /// Reads attributes from the current stream position, advancing Idx. + void readOrDeferAttributes(AttrVec &Attrs, Decl *D); + /// Read an BTFTypeTagAttr object. BTFTypeTagAttr *readBTFTypeTagAttr() { return cast<BTFTypeTagAttr>(readAttr()); @@ -355,6 +361,10 @@ class ASTRecordReader SwitchCase *getSwitchCaseWithID(unsigned ID) { return Reader->getSwitchCaseWithID(ID); } + +private: + Attr *readOrDeferAttrImpl(Decl *D); + void readOrDeferAttributesImpl(AttrVec &Attrs, Decl *D); }; /// Helper class that saves the current stream position and diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index b53f99732cacce..57d1d4d696290d 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -10079,6 +10079,11 @@ void ASTReader::finishPendingActions() { } PendingDeducedVarTypes.clear(); + // Load the delayed preferred name attributes. + for (unsigned I = 0; I != PendingDeferredAttributes.size(); ++I) + loadDeferredAttribute(PendingDeferredAttributes[I]); + PendingDeferredAttributes.clear(); + // For each decl chain that we wanted to complete while deserializing, mark // it as "still needs to be completed". for (unsigned I = 0; I != PendingIncompleteDeclChains.size(); ++I) { diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index dee5169ae5723a..043bed8dc7f382 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -612,7 +612,7 @@ void ASTDeclReader::VisitDecl(Decl *D) { if (HasAttrs) { AttrVec Attrs; - Record.readAttributes(Attrs); + Record.readOrDeferAttributes(Attrs, D); // Avoid calling setAttrs() directly because it uses Decl::getASTContext() // internally which is unsafe during derialization. D->setAttrsImpl(Attrs, Reader.getContext()); @@ -3118,13 +3118,18 @@ class AttrReader { return Reader.readVersionTuple(); } + void skipInts(unsigned N) { Reader.skipInts(N); } + + unsigned getCurrentIdx() { return Reader.getIdx(); } + OMPTraitInfo *readOMPTraitInfo() { return Reader.readOMPTraitInfo(); } template <typename T> T *readDeclAs() { return Reader.readDeclAs<T>(); } }; } -Attr *ASTRecordReader::readAttr() { +/// Reads one attribute from the current stream position, advancing Idx. +Attr *ASTRecordReader::readOrDeferAttrImpl(Decl *D) { AttrReader Record(*this); auto V = Record.readInt(); if (!V) @@ -3134,6 +3139,20 @@ Attr *ASTRecordReader::readAttr() { // Kind is stored as a 1-based integer because 0 is used to indicate a null // Attr pointer. auto Kind = static_cast<attr::Kind>(V - 1); + // Some attributes refer to themselves during deserialization, thus + // their deserialization must be deferred until their underlying type + // is resolved. + if (Kind == attr::PreferredName) { + if (D != nullptr) { + Reader->PendingDeferredAttributes.push_back( + {Record.getCurrentIdx() - 1, D}); + auto SkipCount = Record.readInt(); + Record.skipInts(SkipCount); + return nullptr; + } + // Ignore the skip count when resolving pending actions. + Record.readInt(); + } ASTContext &Context = getContext(); IdentifierInfo *AttrName = Record.readIdentifier(); @@ -3159,13 +3178,31 @@ Attr *ASTRecordReader::readAttr() { return New; } -/// Reads attributes from the current stream position. -void ASTRecordReader::readAttributes(AttrVec &Attrs) { +void ASTRecordReader::readOrDeferAttributesImpl(AttrVec &Attrs, Decl *D) { for (unsigned I = 0, E = readInt(); I != E; ++I) - if (auto *A = readAttr()) + if (auto *A = readOrDeferAttr(D)) Attrs.push_back(A); } +Attr *ASTRecordReader::readAttr() { return readOrDeferAttrImpl(nullptr); } + +/// Reads attributes from the current stream position. +void ASTRecordReader::readAttributes(AttrVec &Attrs) { + readOrDeferAttributesImpl(Attrs, nullptr); +} + +/// Reads one attribute from the current stream position, advancing Idx. +/// For some attributes (where type depends on itself recursively), defer +/// reading the attribute until the type has been read. +Attr *ASTRecordReader::readOrDeferAttr(Decl *D) { return readOrDeferAttrImpl(D); } + +/// Reads attributes from the current stream position, advancing Idx. +/// For some attributes (where type depends on itself recursively), defer +/// reading the attribute until the type has been read. +void ASTRecordReader::readOrDeferAttributes(AttrVec &Attrs, Decl *D) { + readOrDeferAttributesImpl(Attrs, D); +} + //===----------------------------------------------------------------------===// // ASTReader Implementation //===----------------------------------------------------------------------===// @@ -4424,6 +4461,50 @@ void ASTReader::loadPendingDeclChain(Decl *FirstLocal, uint64_t LocalOffset) { ASTDeclReader::attachLatestDecl(CanonDecl, MostRecent); } +void ASTReader::loadDeferredAttribute( + const DeferredAttribute &DA) { + Decl *D = DA.ParentDecl; + ModuleFile *M = getOwningModuleFile(D); + + unsigned LocalDeclIndex = D->getGlobalID().getLocalDeclIndex(); + const DeclOffset &DOffs = M->DeclOffsets[LocalDeclIndex]; + RecordLocation Loc(M, DOffs.getBitOffset(M->DeclsBlockStartOffset)); + + llvm::BitstreamCursor &Cursor = Loc.F->DeclsCursor; + SavedStreamPosition SavedPosition(Cursor); + if (llvm::Error Err = Cursor.JumpToBit(Loc.Offset)) { + Error(std::move(Err)); + } + + Expected<unsigned> MaybeCode = Cursor.ReadCode(); + if (!MaybeCode) { + llvm::report_fatal_error( + Twine("ASTReader::loadPreferredNameAttribute failed reading code: ") + + toString(MaybeCode.takeError())); + } + unsigned Code = MaybeCode.get(); + + ASTRecordReader Record(*this, *Loc.F); + Expected<unsigned> MaybeRecCode = Record.readRecord(Cursor, Code); + if (!MaybeRecCode) { + llvm::report_fatal_error( + Twine( + "ASTReader::loadPreferredNameAttribute failed reading rec code: ") + + toString(MaybeCode.takeError())); + } + unsigned RecCode = MaybeRecCode.get(); + if (RecCode < DECL_TYPEDEF || RecCode > DECL_LAST) { + llvm::report_fatal_error( + Twine("ASTReader::loadPreferredNameAttribute failed reading rec code: " + "expected valid DeclCode") + + toString(MaybeCode.takeError())); + } + + Record.skipInts(DA.RecordIdx); + Attr *A = Record.readOrDeferAttr(nullptr); + getContext().getDeclAttrs(D).push_back(A); +} + namespace { /// Given an ObjC interface, goes through the modules and links to the diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 39004fd4d4c376..d24ca08e1cc988 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -37,6 +37,7 @@ #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeLocVisitor.h" +#include "clang/Basic/AttrKinds.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/FileEntry.h" @@ -4906,15 +4907,17 @@ void ASTWriter::WriteModuleFileExtension(Sema &SemaRef, void ASTRecordWriter::AddAttr(const Attr *A) { auto &Record = *this; - // FIXME: Clang can't handle the serialization/deserialization of - // preferred_name properly now. See - // https://github.com/llvm/llvm-project/issues/56490 for example. - if (!A || (isa<PreferredNameAttr>(A) && - Writer->isWritingStdCXXNamedModules())) + if (!A) return Record.push_back(0); Record.push_back(A->getKind() + 1); // FIXME: stable encoding, target attrs + auto SkipIdx = Record.size(); + if (A->getKind() == attr::PreferredName) { + // Add placeholder for the size of preferred_name attribute. + Record.push_back(0); + } + Record.AddIdentifierRef(A->getAttrName()); Record.AddIdentifierRef(A->getScopeName()); Record.AddSourceRange(A->getRange()); @@ -4925,6 +4928,12 @@ void ASTRecordWriter::AddAttr(const Attr *A) { Record.push_back(A->isRegularKeywordAttribute()); #include "clang/Serialization/AttrPCHWrite.inc" + + if (A->getKind() == attr::PreferredName) { + // Record the actual size of preferred_name attribute (-1 to count the + // placeholder). + Record[SkipIdx] = Record.size() - SkipIdx - 1; + } } /// Emit the list of attributes to the specified record. diff --git a/clang/test/Modules/preferred_name.cppm b/clang/test/Modules/preferred_name.cppm index 806781a81c5ca7..86ba6ae96db998 100644 --- a/clang/test/Modules/preferred_name.cppm +++ b/clang/test/Modules/preferred_name.cppm @@ -53,10 +53,16 @@ import A; export using ::foo_templ; //--- Use1.cpp -import A; // expected-warning@foo.h:8 {{attribute declaration must precede definition}} -#include "foo.h" // expected-note@foo.h:9 {{previous definition is here}} - +// expected-no-diagnostics +import A; +#include "foo.h" //--- Use2.cpp // expected-no-diagnostics #include "foo.h" import A; + +//--- Use3.cpp +#include "foo.h" +import A; +foo test; +int size = test.size(); // expected-error {{no member named 'size' in 'foo'}} >From e70138755a941693dde0179910b0ecbc427b6cb6 Mon Sep 17 00:00:00 2001 From: Viktoriia Bakalova <bakal...@google.com> Date: Tue, 14 Jan 2025 14:13:05 +0100 Subject: [PATCH 2/4] Fix formatting. --- clang/lib/Serialization/ASTReaderDecl.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 043bed8dc7f382..7dedccdb31caf6 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -3194,7 +3194,9 @@ void ASTRecordReader::readAttributes(AttrVec &Attrs) { /// Reads one attribute from the current stream position, advancing Idx. /// For some attributes (where type depends on itself recursively), defer /// reading the attribute until the type has been read. -Attr *ASTRecordReader::readOrDeferAttr(Decl *D) { return readOrDeferAttrImpl(D); } +Attr *ASTRecordReader::readOrDeferAttr(Decl *D) { + return readOrDeferAttrImpl(D); +} /// Reads attributes from the current stream position, advancing Idx. /// For some attributes (where type depends on itself recursively), defer @@ -4461,8 +4463,7 @@ void ASTReader::loadPendingDeclChain(Decl *FirstLocal, uint64_t LocalOffset) { ASTDeclReader::attachLatestDecl(CanonDecl, MostRecent); } -void ASTReader::loadDeferredAttribute( - const DeferredAttribute &DA) { +void ASTReader::loadDeferredAttribute(const DeferredAttribute &DA) { Decl *D = DA.ParentDecl; ModuleFile *M = getOwningModuleFile(D); >From eb6b91527f890a57e1b454b8cc9a9c50e205f0fb Mon Sep 17 00:00:00 2001 From: Viktoriia Bakalova <bakal...@google.com> Date: Thu, 16 Jan 2025 09:28:56 +0100 Subject: [PATCH 3/4] [Modules] Add DeferDeserialization field to attributes. Address other review comments. --- clang/include/clang/AST/Attr.h | 14 +++-- clang/include/clang/Basic/Attr.td | 5 ++ clang/include/clang/Serialization/ASTReader.h | 3 +- .../clang/Serialization/ASTRecordReader.h | 17 ++---- clang/lib/Serialization/ASTReaderDecl.cpp | 55 ++++++++----------- clang/lib/Serialization/ASTWriter.cpp | 15 ++--- clang/utils/TableGen/ClangAttrEmitter.cpp | 4 ++ 7 files changed, 54 insertions(+), 59 deletions(-) diff --git a/clang/include/clang/AST/Attr.h b/clang/include/clang/AST/Attr.h index 3365ebe4d9012b..bed532a84a1bde 100644 --- a/clang/include/clang/AST/Attr.h +++ b/clang/include/clang/AST/Attr.h @@ -60,6 +60,8 @@ class Attr : public AttributeCommonInfo { unsigned IsLateParsed : 1; LLVM_PREFERRED_TYPE(bool) unsigned InheritEvenIfAlreadyPresent : 1; + LLVM_PREFERRED_TYPE(bool) + unsigned DeferDeserialization : 1; void *operator new(size_t bytes) noexcept { llvm_unreachable("Attrs cannot be allocated with regular 'new'."); @@ -80,10 +82,11 @@ class Attr : public AttributeCommonInfo { protected: Attr(ASTContext &Context, const AttributeCommonInfo &CommonInfo, - attr::Kind AK, bool IsLateParsed) + attr::Kind AK, bool IsLateParsed, bool DeferDeserialization = false) : AttributeCommonInfo(CommonInfo), AttrKind(AK), Inherited(false), IsPackExpansion(false), Implicit(false), IsLateParsed(IsLateParsed), - InheritEvenIfAlreadyPresent(false) {} + InheritEvenIfAlreadyPresent(false), + DeferDeserialization(DeferDeserialization) {} public: attr::Kind getKind() const { return static_cast<attr::Kind>(AttrKind); } @@ -105,6 +108,8 @@ class Attr : public AttributeCommonInfo { void setPackExpansion(bool PE) { IsPackExpansion = PE; } bool isPackExpansion() const { return IsPackExpansion; } + bool shouldDeferDeserialization() const { return DeferDeserialization; } + // Clone this attribute. Attr *clone(ASTContext &C) const; @@ -146,8 +151,9 @@ class InheritableAttr : public Attr { protected: InheritableAttr(ASTContext &Context, const AttributeCommonInfo &CommonInfo, attr::Kind AK, bool IsLateParsed, - bool InheritEvenIfAlreadyPresent) - : Attr(Context, CommonInfo, AK, IsLateParsed) { + bool InheritEvenIfAlreadyPresent, + bool DeferDeserialization = false) + : Attr(Context, CommonInfo, AK, IsLateParsed, DeferDeserialization) { this->InheritEvenIfAlreadyPresent = InheritEvenIfAlreadyPresent; } diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 5039c20d8b73be..c06e060f576dc9 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -713,6 +713,10 @@ class Attr { // attribute may be documented under multiple categories, more than one // Documentation entry may be listed. list<Documentation> Documentation; + // Set to true if deserialization of this attribute must be deferred until + // the parent Decl is fully deserialized (during header module file + // deserialization). + bit DeferDeserialization = 0; } /// Used to define a set of mutually exclusive attributes. @@ -3240,6 +3244,7 @@ def PreferredName : InheritableAttr { let InheritEvenIfAlreadyPresent = 1; let MeaningfulToClassTemplateDefinition = 1; let TemplateDependent = 1; + let DeferDeserialization = 1; } def PreserveMost : DeclOrTypeAttr { diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index 4fd51eabe701ba..fc030b820688d3 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -1212,9 +1212,10 @@ class ASTReader /// More attributes that store TypeSourceInfo might be potentially affected, /// see https://github.com/llvm/llvm-project/issues/56490 for details. struct DeferredAttribute { + // Index of the deferred attribute in the Record of the TargetedDecl. uint64_t RecordIdx; // Decl to attach a deferred attribute to. - Decl *ParentDecl; + Decl *TargetedDecl; }; /// The collection of Decls that have been loaded but some of their attributes diff --git a/clang/include/clang/Serialization/ASTRecordReader.h b/clang/include/clang/Serialization/ASTRecordReader.h index b1572ecef9028c..a62c033a9045b8 100644 --- a/clang/include/clang/Serialization/ASTRecordReader.h +++ b/clang/include/clang/Serialization/ASTRecordReader.h @@ -335,18 +335,15 @@ class ASTRecordReader Attr *readAttr(); /// Reads attributes from the current stream position, advancing Idx. - void readAttributes(AttrVec &Attrs); + /// For some attributes (where type depends on itself recursively), defer + /// reading the attribute until the type has been read. + void readAttributes(AttrVec &Attrs, Decl *D = nullptr); /// Reads one attribute from the current stream position, advancing Idx. - Attr *readOrDeferAttr(Decl *D); - - /// Reads attributes from the current stream position, advancing Idx. - void readOrDeferAttributes(AttrVec &Attrs, Decl *D); + Attr *readOrDeferAttrFor(Decl *D); /// Read an BTFTypeTagAttr object. - BTFTypeTagAttr *readBTFTypeTagAttr() { - return cast<BTFTypeTagAttr>(readAttr()); - } + BTFTypeTagAttr *readBTFTypeTagAttr(); /// Reads a token out of a record, advancing Idx. Token readToken() { @@ -361,10 +358,6 @@ class ASTRecordReader SwitchCase *getSwitchCaseWithID(unsigned ID) { return Reader->getSwitchCaseWithID(ID); } - -private: - Attr *readOrDeferAttrImpl(Decl *D); - void readOrDeferAttributesImpl(AttrVec &Attrs, Decl *D); }; /// Helper class that saves the current stream position and diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 7dedccdb31caf6..3c46ced5c3469d 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -612,7 +612,7 @@ void ASTDeclReader::VisitDecl(Decl *D) { if (HasAttrs) { AttrVec Attrs; - Record.readOrDeferAttributes(Attrs, D); + Record.readAttributes(Attrs, D); // Avoid calling setAttrs() directly because it uses Decl::getASTContext() // internally which is unsafe during derialization. D->setAttrsImpl(Attrs, Reader.getContext()); @@ -3129,7 +3129,7 @@ class AttrReader { } /// Reads one attribute from the current stream position, advancing Idx. -Attr *ASTRecordReader::readOrDeferAttrImpl(Decl *D) { +Attr *ASTRecordReader::readAttr() { AttrReader Record(*this); auto V = Record.readInt(); if (!V) @@ -3139,20 +3139,6 @@ Attr *ASTRecordReader::readOrDeferAttrImpl(Decl *D) { // Kind is stored as a 1-based integer because 0 is used to indicate a null // Attr pointer. auto Kind = static_cast<attr::Kind>(V - 1); - // Some attributes refer to themselves during deserialization, thus - // their deserialization must be deferred until their underlying type - // is resolved. - if (Kind == attr::PreferredName) { - if (D != nullptr) { - Reader->PendingDeferredAttributes.push_back( - {Record.getCurrentIdx() - 1, D}); - auto SkipCount = Record.readInt(); - Record.skipInts(SkipCount); - return nullptr; - } - // Ignore the skip count when resolving pending actions. - Record.readInt(); - } ASTContext &Context = getContext(); IdentifierInfo *AttrName = Record.readIdentifier(); @@ -3178,31 +3164,34 @@ Attr *ASTRecordReader::readOrDeferAttrImpl(Decl *D) { return New; } -void ASTRecordReader::readOrDeferAttributesImpl(AttrVec &Attrs, Decl *D) { +/// Reads attributes from the current stream position, advancing Idx. +/// For some attributes (where type depends on itself recursively), defer +/// reading the attribute until the type has been read. +void ASTRecordReader::readAttributes(AttrVec &Attrs, Decl *D) { for (unsigned I = 0, E = readInt(); I != E; ++I) - if (auto *A = readOrDeferAttr(D)) + if (auto *A = readOrDeferAttrFor(D)) Attrs.push_back(A); } -Attr *ASTRecordReader::readAttr() { return readOrDeferAttrImpl(nullptr); } - -/// Reads attributes from the current stream position. -void ASTRecordReader::readAttributes(AttrVec &Attrs) { - readOrDeferAttributesImpl(Attrs, nullptr); -} /// Reads one attribute from the current stream position, advancing Idx. /// For some attributes (where type depends on itself recursively), defer /// reading the attribute until the type has been read. -Attr *ASTRecordReader::readOrDeferAttr(Decl *D) { - return readOrDeferAttrImpl(D); +Attr *ASTRecordReader::readOrDeferAttrFor(Decl *D) { + AttrReader Record(*this); + unsigned SkipCount = Record.readInt(); + if (!SkipCount) + return readAttr(); + Reader->PendingDeferredAttributes.push_back({Record.getCurrentIdx(), D}); + Record.skipInts(SkipCount); + return nullptr; } -/// Reads attributes from the current stream position, advancing Idx. -/// For some attributes (where type depends on itself recursively), defer -/// reading the attribute until the type has been read. -void ASTRecordReader::readOrDeferAttributes(AttrVec &Attrs, Decl *D) { - readOrDeferAttributesImpl(Attrs, D); +BTFTypeTagAttr *ASTRecordReader::readBTFTypeTagAttr() { + AttrReader Record(*this); + // Read and ignore the skip count, since this attribute is not deferred. + Record.readInt(); + return cast<BTFTypeTagAttr>(readAttr()); } //===----------------------------------------------------------------------===// @@ -4464,7 +4453,7 @@ void ASTReader::loadPendingDeclChain(Decl *FirstLocal, uint64_t LocalOffset) { } void ASTReader::loadDeferredAttribute(const DeferredAttribute &DA) { - Decl *D = DA.ParentDecl; + Decl *D = DA.TargetedDecl; ModuleFile *M = getOwningModuleFile(D); unsigned LocalDeclIndex = D->getGlobalID().getLocalDeclIndex(); @@ -4502,7 +4491,7 @@ void ASTReader::loadDeferredAttribute(const DeferredAttribute &DA) { } Record.skipInts(DA.RecordIdx); - Attr *A = Record.readOrDeferAttr(nullptr); + Attr *A = Record.readAttr(); getContext().getDeclAttrs(D).push_back(A); } diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index d24ca08e1cc988..cb4ded90182f13 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -4910,14 +4910,11 @@ void ASTRecordWriter::AddAttr(const Attr *A) { if (!A) return Record.push_back(0); - Record.push_back(A->getKind() + 1); // FIXME: stable encoding, target attrs - auto SkipIdx = Record.size(); - if (A->getKind() == attr::PreferredName) { - // Add placeholder for the size of preferred_name attribute. - Record.push_back(0); - } + // Add placeholder for the size of deferred attribute. + Record.push_back(0); + Record.push_back(A->getKind() + 1); // FIXME: stable encoding, target attrs Record.AddIdentifierRef(A->getAttrName()); Record.AddIdentifierRef(A->getScopeName()); Record.AddSourceRange(A->getRange()); @@ -4929,9 +4926,9 @@ void ASTRecordWriter::AddAttr(const Attr *A) { #include "clang/Serialization/AttrPCHWrite.inc" - if (A->getKind() == attr::PreferredName) { - // Record the actual size of preferred_name attribute (-1 to count the - // placeholder). + if (A->shouldDeferDeserialization()) { + // Record the actual size of deferred attribute (-1 to count the size bit + // itself). Record[SkipIdx] = Record.size() - SkipIdx - 1; } } diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp index cc6a8eaebd44ec..41730eba32ce27 100644 --- a/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -3043,6 +3043,10 @@ static void emitAttributes(const RecordKeeper &Records, raw_ostream &OS, << (R.getValueAsBit("InheritEvenIfAlreadyPresent") ? "true" : "false"); } + if (R.getValueAsBit("DeferDeserialization")) { + OS << ", " + << "/*DeferDeserialization=*/true"; + } OS << ")\n"; for (auto const &ai : Args) { >From f57f83f93b59c8d8b4f50ed6e4bd24543392f722 Mon Sep 17 00:00:00 2001 From: Viktoriia Bakalova <bakal...@google.com> Date: Thu, 16 Jan 2025 09:39:54 +0100 Subject: [PATCH 4/4] [Modules] Fix formatting. --- clang/lib/Serialization/ASTReaderDecl.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 3c46ced5c3469d..5a841ee31bd594 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -3173,7 +3173,6 @@ void ASTRecordReader::readAttributes(AttrVec &Attrs, Decl *D) { Attrs.push_back(A); } - /// Reads one attribute from the current stream position, advancing Idx. /// For some attributes (where type depends on itself recursively), defer /// reading the attribute until the type has been read. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits