Author: Chuanqi Xu Date: 2025-01-17T21:03:53+08:00 New Revision: fb2c9d940ad87e6ae09e06c6915e0c925a4f87ec
URL: https://github.com/llvm/llvm-project/commit/fb2c9d940ad87e6ae09e06c6915e0c925a4f87ec DIFF: https://github.com/llvm/llvm-project/commit/fb2c9d940ad87e6ae09e06c6915e0c925a4f87ec.diff LOG: [C++20] [Modules] Makes sure internal declaration won't be found by other TU (#123059) Close https://github.com/llvm/llvm-project/issues/61427 And this is also helpful to implement https://github.com/llvm/llvm-project/issues/112294 partially. The implementation strategy mimics https://github.com/llvm/llvm-project/pull/122887. This patch split the internal declarations from the general lookup table so that other TU can't find the internal declarations. Added: Modified: clang/include/clang/Serialization/ASTBitCodes.h clang/include/clang/Serialization/ASTReader.h clang/include/clang/Serialization/ASTWriter.h clang/lib/Serialization/ASTReader.cpp clang/lib/Serialization/ASTReaderDecl.cpp clang/lib/Serialization/ASTWriter.cpp clang/lib/Serialization/ASTWriterDecl.cpp clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p5-ex2.cpp clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp clang/test/CXX/module/basic/basic.def.odr/p4.cppm clang/test/CXX/module/basic/basic.link/p2.cppm Removed: ################################################################################ diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h index 40dae25f7b54b7..d568d2fd7aa301 100644 --- a/clang/include/clang/Serialization/ASTBitCodes.h +++ b/clang/include/clang/Serialization/ASTBitCodes.h @@ -740,6 +740,8 @@ enum ASTRecordTypes { CXX_ADDED_TEMPLATE_PARTIAL_SPECIALIZATION = 75, UPDATE_MODULE_LOCAL_VISIBLE = 76, + + UPDATE_TU_LOCAL_VISIBLE = 77, }; /// Record types used within a source manager block. @@ -1340,6 +1342,10 @@ enum DeclCode { /// only visible from DeclContext in the same module. DECL_CONTEXT_MODULE_LOCAL_VISIBLE, + /// A record that stores the set of declarations that are only visible + /// to the TU. + DECL_CONTEXT_TU_LOCAL_VISIBLE, + /// A LabelDecl record. DECL_LABEL, diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index c839215dc40778..82564fe664acba 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -528,6 +528,7 @@ class ASTReader uint64_t LexicalOffset; uint64_t VisibleOffset; uint64_t ModuleLocalOffset; + uint64_t TULocalOffset; }; using DelayedNamespaceOffsetMapTy = @@ -640,6 +641,9 @@ class ASTReader llvm::DenseMap<const DeclContext *, serialization::reader::ModuleLocalLookupTable> ModuleLocalLookups; + llvm::DenseMap<const DeclContext *, + serialization::reader::DeclContextLookupTable> + TULocalLookups; using SpecLookupTableTy = llvm::DenseMap<const Decl *, @@ -670,6 +674,7 @@ class ASTReader llvm::DenseMap<GlobalDeclID, DeclContextVisibleUpdates> PendingVisibleUpdates; llvm::DenseMap<GlobalDeclID, DeclContextVisibleUpdates> PendingModuleLocalVisibleUpdates; + llvm::DenseMap<GlobalDeclID, DeclContextVisibleUpdates> TULocalUpdates; using SpecializationsUpdate = SmallVector<UpdateData, 1>; using SpecializationsUpdateMap = @@ -704,11 +709,17 @@ class ASTReader llvm::BitstreamCursor &Cursor, uint64_t Offset, DeclContext *DC); + enum class VisibleDeclContextStorageKind { + GenerallyVisible, + ModuleLocalVisible, + TULocalVisible, + }; + /// Read the record that describes the visible contents of a DC. bool ReadVisibleDeclContextStorage(ModuleFile &M, llvm::BitstreamCursor &Cursor, uint64_t Offset, GlobalDeclID ID, - bool IsModuleLocal); + VisibleDeclContextStorageKind VisibleKind); bool ReadSpecializations(ModuleFile &M, llvm::BitstreamCursor &Cursor, uint64_t Offset, Decl *D, bool IsPartial); @@ -1148,6 +1159,10 @@ class ASTReader unsigned NumModuleLocalVisibleDeclContexts = 0, TotalModuleLocalVisibleDeclContexts = 0; + /// Number of TU Local decl contexts read/total + unsigned NumTULocalVisibleDeclContexts = 0, + TotalTULocalVisibleDeclContexts = 0; + /// Total size of modules, in bits, currently loaded uint64_t TotalModulesSizeInBits = 0; @@ -1481,6 +1496,9 @@ class ASTReader const serialization::reader::ModuleLocalLookupTable * getModuleLocalLookupTables(DeclContext *Primary) const; + const serialization::reader::DeclContextLookupTable * + getTULocalLookupTables(DeclContext *Primary) const; + /// Get the loaded specializations lookup tables for \p D, /// if any. serialization::reader::LazySpecializationInfoLookupTable * diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index 53b09cc914392e..079e39a9fb678b 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -496,6 +496,9 @@ class ASTWriter : public ASTDeserializationListener, /// file. unsigned NumModuleLocalDeclContexts = 0; + /// The number of TULocal declcontexts written to the AST file. + unsigned NumTULocalDeclContexts = 0; + /// A mapping from each known submodule to its ID number, which will /// be a positive integer. llvm::DenseMap<const Module *, unsigned> SubmoduleIDs; @@ -594,12 +597,14 @@ class ASTWriter : public ASTDeserializationListener, void GenerateNameLookupTable(ASTContext &Context, const DeclContext *DC, llvm::SmallVectorImpl<char> &LookupTable, - llvm::SmallVectorImpl<char> &ModuleLocalLookupTable); + llvm::SmallVectorImpl<char> &ModuleLocalLookupTable, + llvm::SmallVectorImpl<char> &TULocalLookupTable); uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, const DeclContext *DC); void WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC, uint64_t &VisibleBlockOffset, - uint64_t &ModuleLocalBlockOffset); + uint64_t &ModuleLocalBlockOffset, + uint64_t &TULocalBlockOffset); void WriteTypeDeclOffsets(); void WriteFileDeclIDsMap(); void WriteComments(ASTContext &Context); @@ -633,8 +638,10 @@ class ASTWriter : public ASTDeserializationListener, unsigned DeclContextLexicalAbbrev = 0; unsigned DeclContextVisibleLookupAbbrev = 0; unsigned DeclModuleLocalVisibleLookupAbbrev = 0; + unsigned DeclTULocalLookupAbbrev = 0; unsigned UpdateVisibleAbbrev = 0; unsigned ModuleLocalUpdateVisibleAbbrev = 0; + unsigned TULocalUpdateVisibleAbbrev = 0; unsigned DeclRecordAbbrev = 0; unsigned DeclTypedefAbbrev = 0; unsigned DeclVarAbbrev = 0; diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index d08dc6b1b4d938..a72ff766685bbe 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -1425,10 +1425,9 @@ bool ASTReader::ReadLexicalDeclContextStorage(ModuleFile &M, return false; } -bool ASTReader::ReadVisibleDeclContextStorage(ModuleFile &M, - BitstreamCursor &Cursor, - uint64_t Offset, GlobalDeclID ID, - bool IsModuleLocal) { +bool ASTReader::ReadVisibleDeclContextStorage( + ModuleFile &M, BitstreamCursor &Cursor, uint64_t Offset, GlobalDeclID ID, + ASTReader::VisibleDeclContextStorageKind VisibleKind) { assert(Offset != 0); SavedStreamPosition SavedPosition(Cursor); @@ -1452,22 +1451,42 @@ bool ASTReader::ReadVisibleDeclContextStorage(ModuleFile &M, return true; } unsigned RecCode = MaybeRecCode.get(); - if (!IsModuleLocal && RecCode != DECL_CONTEXT_VISIBLE) { - Error("Expected visible lookup table block"); - return true; - } - if (IsModuleLocal && RecCode != DECL_CONTEXT_MODULE_LOCAL_VISIBLE) { - Error("Expected module local visible lookup table block"); - return true; + switch (VisibleKind) { + case VisibleDeclContextStorageKind::GenerallyVisible: + if (RecCode != DECL_CONTEXT_VISIBLE) { + Error("Expected visible lookup table block"); + return true; + } + break; + case VisibleDeclContextStorageKind::ModuleLocalVisible: + if (RecCode != DECL_CONTEXT_MODULE_LOCAL_VISIBLE) { + Error("Expected module local visible lookup table block"); + return true; + } + break; + case VisibleDeclContextStorageKind::TULocalVisible: + if (RecCode != DECL_CONTEXT_TU_LOCAL_VISIBLE) { + Error("Expected TU local lookup table block"); + return true; + } + break; } // We can't safely determine the primary context yet, so delay attaching the // lookup table until we're done with recursive deserialization. auto *Data = (const unsigned char*)Blob.data(); - if (!IsModuleLocal) + switch (VisibleKind) { + case VisibleDeclContextStorageKind::GenerallyVisible: PendingVisibleUpdates[ID].push_back(UpdateData{&M, Data}); - else + break; + case VisibleDeclContextStorageKind::ModuleLocalVisible: PendingModuleLocalVisibleUpdates[ID].push_back(UpdateData{&M, Data}); + break; + case VisibleDeclContextStorageKind::TULocalVisible: + if (M.Kind == MK_MainFile) + TULocalUpdates[ID].push_back(UpdateData{&M, Data}); + break; + } return false; } @@ -3613,6 +3632,21 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, break; } + case UPDATE_TU_LOCAL_VISIBLE: { + if (F.Kind != MK_MainFile) + break; + unsigned Idx = 0; + GlobalDeclID ID = ReadDeclID(F, Record, Idx); + auto *Data = (const unsigned char *)Blob.data(); + TULocalUpdates[ID].push_back(UpdateData{&F, Data}); + // If we've already loaded the decl, perform the updates when we finish + // loading this block. + if (Decl *D = GetExistingDecl(ID)) + PendingUpdateRecords.push_back( + PendingUpdateRecord(ID, D, /*JustLoaded=*/false)); + break; + } + case CXX_ADDED_TEMPLATE_SPECIALIZATION: { unsigned Idx = 0; GlobalDeclID ID = ReadDeclID(F, Record, Idx); @@ -3717,6 +3751,7 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, TotalLexicalDeclContexts += Record[2]; TotalVisibleDeclContexts += Record[3]; TotalModuleLocalVisibleDeclContexts += Record[4]; + TotalTULocalVisibleDeclContexts += Record[5]; break; case UNUSED_FILESCOPED_DECLS: @@ -4002,7 +4037,7 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, break; case DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD: { - if (Record.size() % 4 != 0) + if (Record.size() % 5 != 0) return llvm::createStringError( std::errc::illegal_byte_sequence, "invalid DELAYED_NAMESPACE_LEXICAL_VISIBLE_RECORD block in AST " @@ -4021,9 +4056,12 @@ llvm::Error ASTReader::ReadASTBlock(ModuleFile &F, uint64_t LocalModuleLocalOffset = Record[I++]; uint64_t ModuleLocalOffset = LocalModuleLocalOffset ? BaseOffset + LocalModuleLocalOffset : 0; + uint64_t TULocalLocalOffset = Record[I++]; + uint64_t TULocalOffset = + TULocalLocalOffset ? BaseOffset + TULocalLocalOffset : 0; DelayedNamespaceOffsetMap[ID] = {LexicalOffset, VisibleOffset, - ModuleLocalOffset}; + ModuleLocalOffset, TULocalOffset}; assert(!GetExistingDecl(ID) && "We shouldn't load the namespace in the front of delayed " @@ -8473,6 +8511,15 @@ bool ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC, } } + if (auto It = TULocalLookups.find(DC); It != TULocalLookups.end()) { + ++NumTULocalVisibleDeclContexts; + for (GlobalDeclID ID : It->second.Table.find(Name)) { + NamedDecl *ND = cast<NamedDecl>(GetDecl(ID)); + if (ND->getDeclName() == Name && Found.insert(ND).second) + Decls.push_back(ND); + } + } + SetExternalVisibleDeclsForName(DC, Name, Decls); return !Decls.empty(); } @@ -8500,6 +8547,7 @@ void ASTReader::completeVisibleDeclsMap(const DeclContext *DC) { findAll(Lookups, NumVisibleDeclContextsRead); findAll(ModuleLocalLookups, NumModuleLocalVisibleDeclContexts); + findAll(TULocalLookups, NumTULocalVisibleDeclContexts); for (DeclsMap::iterator I = Decls.begin(), E = Decls.end(); I != E; ++I) { SetExternalVisibleDeclsForName(DC, I->first, I->second); @@ -8519,6 +8567,12 @@ ASTReader::getModuleLocalLookupTables(DeclContext *Primary) const { return I == ModuleLocalLookups.end() ? nullptr : &I->second; } +const serialization::reader::DeclContextLookupTable * +ASTReader::getTULocalLookupTables(DeclContext *Primary) const { + auto I = TULocalLookups.find(Primary); + return I == TULocalLookups.end() ? nullptr : &I->second; +} + serialization::reader::LazySpecializationInfoLookupTable * ASTReader::getLoadedSpecializationsLookupTables(const Decl *D, bool IsPartial) { assert(D->isCanonicalDecl()); @@ -8634,6 +8688,11 @@ void ASTReader::PrintStats() { NumModuleLocalVisibleDeclContexts, TotalModuleLocalVisibleDeclContexts, ((float)NumModuleLocalVisibleDeclContexts / TotalModuleLocalVisibleDeclContexts * 100)); + if (TotalTULocalVisibleDeclContexts) + std::fprintf(stderr, " %u/%u visible declcontexts in GMF read (%f%%)\n", + NumTULocalVisibleDeclContexts, TotalTULocalVisibleDeclContexts, + ((float)NumTULocalVisibleDeclContexts / + TotalTULocalVisibleDeclContexts * 100)); if (TotalNumMethodPoolEntries) std::fprintf(stderr, " %u/%u method pool entries read (%f%%)\n", NumMethodPoolEntriesRead, TotalNumMethodPoolEntries, diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 06dff02ac61280..de834285fa76b2 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -414,7 +414,8 @@ class ASTDeclReader : public DeclVisitor<ASTDeclReader, void> { void VisitLifetimeExtendedTemporaryDecl(LifetimeExtendedTemporaryDecl *D); void VisitDeclContext(DeclContext *DC, uint64_t &LexicalOffset, - uint64_t &VisibleOffset, uint64_t &ModuleLocalOffset); + uint64_t &VisibleOffset, uint64_t &ModuleLocalOffset, + uint64_t &TULocalOffset); template <typename T> RedeclarableResult VisitRedeclarable(Redeclarable<T> *D); @@ -1859,7 +1860,9 @@ void ASTDeclReader::VisitHLSLBufferDecl(HLSLBufferDecl *D) { uint64_t LexicalOffset = 0; uint64_t VisibleOffset = 0; uint64_t ModuleLocalOffset = 0; - VisitDeclContext(D, LexicalOffset, VisibleOffset, ModuleLocalOffset); + uint64_t TULocalOffset = 0; + VisitDeclContext(D, LexicalOffset, VisibleOffset, ModuleLocalOffset, + TULocalOffset); D->IsCBuffer = Record.readBool(); D->KwLoc = readSourceLocation(); D->LBraceLoc = readSourceLocation(); @@ -2770,10 +2773,12 @@ void ASTDeclReader::VisitLifetimeExtendedTemporaryDecl( void ASTDeclReader::VisitDeclContext(DeclContext *DC, uint64_t &LexicalOffset, uint64_t &VisibleOffset, - uint64_t &ModuleLocalOffset) { + uint64_t &ModuleLocalOffset, + uint64_t &TULocalOffset) { LexicalOffset = ReadLocalOffset(); VisibleOffset = ReadLocalOffset(); ModuleLocalOffset = ReadLocalOffset(); + TULocalOffset = ReadLocalOffset(); } template <typename T> @@ -3903,6 +3908,7 @@ Decl *ASTReader::ReadDeclRecord(GlobalDeclID ID) { case DECL_CONTEXT_LEXICAL: case DECL_CONTEXT_VISIBLE: case DECL_CONTEXT_MODULE_LOCAL_VISIBLE: + case DECL_CONTEXT_TU_LOCAL_VISIBLE: case DECL_SPECIALIZATIONS: case DECL_PARTIAL_SPECIALIZATIONS: llvm_unreachable("Record cannot be de-serialized with readDeclRecord"); @@ -4213,9 +4219,10 @@ Decl *ASTReader::ReadDeclRecord(GlobalDeclID ID) { uint64_t LexicalOffset = 0; uint64_t VisibleOffset = 0; uint64_t ModuleLocalOffset = 0; + uint64_t TULocalOffset = 0; - Reader.VisitDeclContext(DC, LexicalOffset, VisibleOffset, - ModuleLocalOffset); + Reader.VisitDeclContext(DC, LexicalOffset, VisibleOffset, ModuleLocalOffset, + TULocalOffset); // Get the lexical and visible block for the delayed namespace. // It is sufficient to judge if ID is in DelayedNamespaceOffsetMap. @@ -4227,18 +4234,24 @@ Decl *ASTReader::ReadDeclRecord(GlobalDeclID ID) { LexicalOffset = Iter->second.LexicalOffset; VisibleOffset = Iter->second.VisibleOffset; ModuleLocalOffset = Iter->second.ModuleLocalOffset; + TULocalOffset = Iter->second.TULocalOffset; } if (LexicalOffset && ReadLexicalDeclContextStorage(*Loc.F, DeclsCursor, LexicalOffset, DC)) return nullptr; - if (VisibleOffset && - ReadVisibleDeclContextStorage(*Loc.F, DeclsCursor, VisibleOffset, ID, - /*IsModuleLocal=*/false)) + if (VisibleOffset && ReadVisibleDeclContextStorage( + *Loc.F, DeclsCursor, VisibleOffset, ID, + VisibleDeclContextStorageKind::GenerallyVisible)) return nullptr; if (ModuleLocalOffset && - ReadVisibleDeclContextStorage(*Loc.F, DeclsCursor, ModuleLocalOffset, - ID, /*IsModuleLocal=*/true)) + ReadVisibleDeclContextStorage( + *Loc.F, DeclsCursor, ModuleLocalOffset, ID, + VisibleDeclContextStorageKind::ModuleLocalVisible)) + return nullptr; + if (TULocalOffset && ReadVisibleDeclContextStorage( + *Loc.F, DeclsCursor, TULocalOffset, ID, + VisibleDeclContextStorageKind::TULocalVisible)) return nullptr; } assert(Record.getIdx() == Record.size()); @@ -4404,6 +4417,18 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { DC->setHasExternalVisibleStorage(true); } + if (auto I = TULocalUpdates.find(ID); I != TULocalUpdates.end()) { + auto Updates = std::move(I->second); + TULocalUpdates.erase(I); + + auto *DC = cast<DeclContext>(D)->getPrimaryContext(); + for (const auto &Update : Updates) + TULocalLookups[DC].Table.add( + Update.Mod, Update.Data, + reader::ASTDeclContextNameLookupTrait(*this, *Update.Mod)); + DC->setHasExternalVisibleStorage(true); + } + // Load any pending related decls. if (D->isCanonicalDecl()) { if (auto IT = RelatedDeclsMap.find(ID); IT != RelatedDeclsMap.end()) { diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 1c4f5730df312b..c7c17e09a30e0a 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -4047,6 +4047,13 @@ class ASTDeclContextNameLookupTraitBase { : Writer(Writer) {} public: + data_type getData(const DeclIDsTy &LocalIDs) { + unsigned Start = DeclIDs.size(); + for (auto ID : LocalIDs) + DeclIDs.push_back(ID); + return std::make_pair(Start, DeclIDs.size()); + } + data_type ImportData(const reader::ASTDeclContextNameLookupTrait::data_type &FromReader) { unsigned Start = DeclIDs.size(); DeclIDs.insert( @@ -4139,23 +4146,16 @@ class ASTDeclContextNameLookupTraitBase { } }; -class ModuleLocalNameLookupTrait : public ASTDeclContextNameLookupTraitBase { +class ModuleLevelNameLookupTrait : public ASTDeclContextNameLookupTraitBase { public: using primary_module_hash_type = unsigned; using key_type = std::pair<DeclarationNameKey, primary_module_hash_type>; using key_type_ref = key_type; - explicit ModuleLocalNameLookupTrait(ASTWriter &Writer) + explicit ModuleLevelNameLookupTrait(ASTWriter &Writer) : ASTDeclContextNameLookupTraitBase(Writer) {} - data_type getData(const DeclIDsTy &LocalIDs) { - unsigned Start = DeclIDs.size(); - for (auto ID : LocalIDs) - DeclIDs.push_back(ID); - return std::make_pair(Start, DeclIDs.size()); - } - static bool EqualKey(key_type_ref a, key_type_ref b) { return a == b; } hash_value_type ComputeHash(key_type Key) { @@ -4203,19 +4203,46 @@ static bool isModuleLocalDecl(NamedDecl *D) { return false; } +static bool isTULocalInNamedModules(NamedDecl *D) { + Module *NamedModule = D->getTopLevelOwningNamedModule(); + if (!NamedModule) + return false; + + // For none-top level decls, we choose to move it to the general visible + // lookup table. Since the consumer may get its parent somehow and performs + // a lookup in it (considering looking up the operator function in lambda). + // The diff erence between module local lookup table and TU local lookup table + // is, the consumers still have a chance to lookup in the module local lookup + // table but **now** the consumers won't read the TU local lookup table if + // the consumer is not the original TU. + // + // FIXME: It seems to be an optimization chance (and also a more correct + // semantics) to remain the TULocal lookup table and performing similar lookup + // with the module local lookup table except that we only allow the lookups + // with the same module unit. + if (!D->getNonTransparentDeclContext()->isFileContext()) + return false; + + return D->getLinkageInternal() == Linkage::Internal; +} + // Trait used for the on-disk hash table used in the method pool. +template <bool CollectingTULocalDecls> class ASTDeclContextNameLookupTrait : public ASTDeclContextNameLookupTraitBase { public: - using ModuleLocalDeclsMapTy = - llvm::DenseMap<ModuleLocalNameLookupTrait::key_type, DeclIDsTy>; - -private: - ModuleLocalDeclsMapTy ModuleLocalDeclsMap; + using ModuleLevelDeclsMapTy = + llvm::DenseMap<ModuleLevelNameLookupTrait::key_type, DeclIDsTy>; -public: using key_type = DeclarationNameKey; using key_type_ref = key_type; + using TULocalDeclsMapTy = llvm::DenseMap<key_type, DeclIDsTy>; + +private: + ModuleLevelDeclsMapTy ModuleLocalDeclsMap; + TULocalDeclsMapTy TULocalDeclsMap; + +public: explicit ASTDeclContextNameLookupTrait(ASTWriter &Writer) : ASTDeclContextNameLookupTraitBase(Writer) {} @@ -4251,15 +4278,30 @@ class ASTDeclContextNameLookupTrait : public ASTDeclContextNameLookupTraitBase { } } + if constexpr (CollectingTULocalDecls) { + if (isTULocalInNamedModules(D)) { + auto Iter = TULocalDeclsMap.find(D->getDeclName()); + if (Iter == TULocalDeclsMap.end()) + TULocalDeclsMap.insert({D->getDeclName(), DeclIDsTy{ID}}); + else + Iter->second.push_back(ID); + continue; + } + } + DeclIDs.push_back(ID); } return std::make_pair(Start, DeclIDs.size()); } - const ModuleLocalDeclsMapTy &getModuleLocalDecls() { + using ASTDeclContextNameLookupTraitBase::getData; + + const ModuleLevelDeclsMapTy &getModuleLocalDecls() { return ModuleLocalDeclsMap; } + const TULocalDeclsMapTy &getTULocalDecls() { return TULocalDeclsMap; } + static bool EqualKey(key_type_ref a, key_type_ref b) { return a == b; } hash_value_type ComputeHash(key_type Name) { return Name.getHash(); } @@ -4487,7 +4529,8 @@ static bool isLookupResultNotInteresting(ASTWriter &Writer, void ASTWriter::GenerateNameLookupTable( ASTContext &Context, const DeclContext *ConstDC, llvm::SmallVectorImpl<char> &LookupTable, - llvm::SmallVectorImpl<char> &ModuleLocalLookupTable) { + llvm::SmallVectorImpl<char> &ModuleLocalLookupTable, + llvm::SmallVectorImpl<char> &TULookupTable) { assert(!ConstDC->hasLazyLocalLexicalLookups() && !ConstDC->hasLazyExternalLexicalLookups() && "must call buildLookups first"); @@ -4497,9 +4540,11 @@ void ASTWriter::GenerateNameLookupTable( assert(DC == DC->getPrimaryContext() && "only primary DC has lookup table"); // Create the on-disk hash table representation. - MultiOnDiskHashTableGenerator<reader::ASTDeclContextNameLookupTrait, - ASTDeclContextNameLookupTrait> Generator; - ASTDeclContextNameLookupTrait Trait(*this); + MultiOnDiskHashTableGenerator< + reader::ASTDeclContextNameLookupTrait, + ASTDeclContextNameLookupTrait</*CollectingTULocal=*/true>> + Generator; + ASTDeclContextNameLookupTrait</*CollectingTULocal=*/true> Trait(*this); // The first step is to collect the declaration names which we need to // serialize into the name lookup table, and to collect them in a stable @@ -4671,26 +4716,45 @@ void ASTWriter::GenerateNameLookupTable( Generator.emit(LookupTable, Trait, Lookups ? &Lookups->Table : nullptr); const auto &ModuleLocalDecls = Trait.getModuleLocalDecls(); - if (ModuleLocalDecls.empty()) - return; + if (!ModuleLocalDecls.empty()) { + MultiOnDiskHashTableGenerator<reader::ModuleLocalNameLookupTrait, + ModuleLevelNameLookupTrait> + ModuleLocalLookupGenerator; + ModuleLevelNameLookupTrait ModuleLocalTrait(*this); + + for (const auto &ModuleLocalIter : ModuleLocalDecls) { + const auto &Key = ModuleLocalIter.first; + const auto &IDs = ModuleLocalIter.second; + ModuleLocalLookupGenerator.insert(Key, ModuleLocalTrait.getData(IDs), + ModuleLocalTrait); + } - MultiOnDiskHashTableGenerator<reader::ModuleLocalNameLookupTrait, - ModuleLocalNameLookupTrait> - ModuleLocalLookupGenerator; - ModuleLocalNameLookupTrait ModuleLocalTrait(*this); + auto *ModuleLocalLookups = + Chain ? Chain->getModuleLocalLookupTables(DC) : nullptr; + ModuleLocalLookupGenerator.emit( + ModuleLocalLookupTable, ModuleLocalTrait, + ModuleLocalLookups ? &ModuleLocalLookups->Table : nullptr); + } + + const auto &TULocalDecls = Trait.getTULocalDecls(); + if (!TULocalDecls.empty() && !isGeneratingReducedBMI()) { + MultiOnDiskHashTableGenerator< + reader::ASTDeclContextNameLookupTrait, + ASTDeclContextNameLookupTrait</*CollectingTULocal=*/false>> + TULookupGenerator; + ASTDeclContextNameLookupTrait</*CollectingTULocal=*/false> TULocalTrait( + *this); + + for (const auto &TULocalIter : TULocalDecls) { + const auto &Key = TULocalIter.first; + const auto &IDs = TULocalIter.second; + TULookupGenerator.insert(Key, TULocalTrait.getData(IDs), TULocalTrait); + } - for (const auto &ModuleLocalIter : ModuleLocalDecls) { - const auto &Key = ModuleLocalIter.first; - const auto &IDs = ModuleLocalIter.second; - ModuleLocalLookupGenerator.insert(Key, ModuleLocalTrait.getData(IDs), - ModuleLocalTrait); + auto *TULocalLookups = Chain ? Chain->getTULocalLookupTables(DC) : nullptr; + TULookupGenerator.emit(TULookupTable, TULocalTrait, + TULocalLookups ? &TULocalLookups->Table : nullptr); } - - auto *ModuleLocalLookups = - Chain ? Chain->getModuleLocalLookupTables(DC) : nullptr; - ModuleLocalLookupGenerator.emit( - ModuleLocalLookupTable, ModuleLocalTrait, - ModuleLocalLookups ? &ModuleLocalLookups->Table : nullptr); } /// Write the block containing all of the declaration IDs @@ -4701,7 +4765,12 @@ void ASTWriter::GenerateNameLookupTable( void ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC, uint64_t &VisibleBlockOffset, - uint64_t &ModuleLocalBlockOffset) { + uint64_t &ModuleLocalBlockOffset, + uint64_t &TULocalBlockOffset) { + assert(VisibleBlockOffset == 0); + assert(ModuleLocalBlockOffset == 0); + assert(TULocalBlockOffset == 0); + // If we imported a key declaration of this namespace, write the visible // lookup results as an update record for it rather than including them // on this declaration. We will only look at key declarations on reload. @@ -4788,7 +4857,9 @@ void ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, // Create the on-disk hash table in a buffer. SmallString<4096> LookupTable; SmallString<4096> ModuleLocalLookupTable; - GenerateNameLookupTable(Context, DC, LookupTable, ModuleLocalLookupTable); + SmallString<4096> TULookupTable; + GenerateNameLookupTable(Context, DC, LookupTable, ModuleLocalLookupTable, + TULookupTable); // Write the lookup table RecordData::value_type Record[] = {DECL_CONTEXT_VISIBLE}; @@ -4796,17 +4867,26 @@ void ASTWriter::WriteDeclContextVisibleBlock(ASTContext &Context, LookupTable); ++NumVisibleDeclContexts; - if (ModuleLocalLookupTable.empty()) - return; + if (!ModuleLocalLookupTable.empty()) { + ModuleLocalBlockOffset = Stream.GetCurrentBitNo(); + assert(ModuleLocalBlockOffset > VisibleBlockOffset); + // Write the lookup table + RecordData::value_type ModuleLocalRecord[] = { + DECL_CONTEXT_MODULE_LOCAL_VISIBLE}; + Stream.EmitRecordWithBlob(DeclModuleLocalVisibleLookupAbbrev, + ModuleLocalRecord, ModuleLocalLookupTable); + ++NumModuleLocalDeclContexts; + } - ModuleLocalBlockOffset = Stream.GetCurrentBitNo(); - assert(ModuleLocalBlockOffset > VisibleBlockOffset); - // Write the lookup table - RecordData::value_type ModuleLocalRecord[] = { - DECL_CONTEXT_MODULE_LOCAL_VISIBLE}; - Stream.EmitRecordWithBlob(DeclModuleLocalVisibleLookupAbbrev, - ModuleLocalRecord, ModuleLocalLookupTable); - ++NumModuleLocalDeclContexts; + if (!TULookupTable.empty()) { + TULocalBlockOffset = Stream.GetCurrentBitNo(); + // Write the lookup table + RecordData::value_type TULocalDeclsRecord[] = { + DECL_CONTEXT_TU_LOCAL_VISIBLE}; + Stream.EmitRecordWithBlob(DeclTULocalLookupAbbrev, TULocalDeclsRecord, + TULookupTable); + ++NumTULocalDeclContexts; + } } /// Write an UPDATE_VISIBLE block for the given context. @@ -4824,7 +4904,9 @@ void ASTWriter::WriteDeclContextVisibleUpdate(ASTContext &Context, // Create the on-disk hash table in a buffer. SmallString<4096> LookupTable; SmallString<4096> ModuleLocalLookupTable; - GenerateNameLookupTable(Context, DC, LookupTable, ModuleLocalLookupTable); + SmallString<4096> TULookupTable; + GenerateNameLookupTable(Context, DC, LookupTable, ModuleLocalLookupTable, + TULookupTable); // If we're updating a namespace, select a key declaration as the key for the // update record; those are the only ones that will be checked on reload. @@ -4836,14 +4918,20 @@ void ASTWriter::WriteDeclContextVisibleUpdate(ASTContext &Context, getDeclID(cast<Decl>(DC)).getRawValue()}; Stream.EmitRecordWithBlob(UpdateVisibleAbbrev, Record, LookupTable); - if (ModuleLocalLookupTable.empty()) - return; + if (!ModuleLocalLookupTable.empty()) { + // Write the module local lookup table + RecordData::value_type ModuleLocalRecord[] = { + UPDATE_MODULE_LOCAL_VISIBLE, getDeclID(cast<Decl>(DC)).getRawValue()}; + Stream.EmitRecordWithBlob(ModuleLocalUpdateVisibleAbbrev, ModuleLocalRecord, + ModuleLocalLookupTable); + } - // Write the module local lookup table - RecordData::value_type ModuleLocalRecord[] = { - UPDATE_MODULE_LOCAL_VISIBLE, getDeclID(cast<Decl>(DC)).getRawValue()}; - Stream.EmitRecordWithBlob(ModuleLocalUpdateVisibleAbbrev, ModuleLocalRecord, - ModuleLocalLookupTable); + if (!TULookupTable.empty()) { + RecordData::value_type GMFRecord[] = { + UPDATE_TU_LOCAL_VISIBLE, getDeclID(cast<Decl>(DC)).getRawValue()}; + Stream.EmitRecordWithBlob(TULocalUpdateVisibleAbbrev, GMFRecord, + TULookupTable); + } } /// Write an FP_PRAGMA_OPTIONS block for the given FPOptions. @@ -6031,9 +6119,12 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema *SemaPtr, StringRef isysroot, } // Some simple statistics - RecordData::value_type Record[] = { - NumStatements, NumMacros, NumLexicalDeclContexts, NumVisibleDeclContexts, - NumModuleLocalDeclContexts}; + RecordData::value_type Record[] = {NumStatements, + NumMacros, + NumLexicalDeclContexts, + NumVisibleDeclContexts, + NumModuleLocalDeclContexts, + NumTULocalDeclContexts}; Stream.EmitRecord(STATISTICS, Record); Stream.ExitBlock(); Stream.FlushToWord(); @@ -6112,7 +6203,9 @@ void ASTWriter::WriteDeclAndTypes(ASTContext &Context) { uint64_t LexicalOffset = WriteDeclContextLexicalBlock(Context, NS); uint64_t VisibleOffset = 0; uint64_t ModuleLocalOffset = 0; - WriteDeclContextVisibleBlock(Context, NS, VisibleOffset, ModuleLocalOffset); + uint64_t TULocalOffset = 0; + WriteDeclContextVisibleBlock(Context, NS, VisibleOffset, ModuleLocalOffset, + TULocalOffset); // Write the offset relative to current block. if (LexicalOffset) @@ -6124,10 +6217,14 @@ void ASTWriter::WriteDeclAndTypes(ASTContext &Context) { if (ModuleLocalOffset) ModuleLocalOffset -= DeclTypesBlockStartOffset; + if (TULocalOffset) + TULocalOffset -= DeclTypesBlockStartOffset; + AddDeclRef(NS, DelayedNamespaceRecord); DelayedNamespaceRecord.push_back(LexicalOffset); DelayedNamespaceRecord.push_back(VisibleOffset); DelayedNamespaceRecord.push_back(ModuleLocalOffset); + DelayedNamespaceRecord.push_back(TULocalOffset); } // The process of writing lexical and visible block for delayed namespace @@ -6213,6 +6310,12 @@ void ASTWriter::WriteDeclAndTypes(ASTContext &Context) { Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); ModuleLocalUpdateVisibleAbbrev = Stream.EmitAbbrev(std::move(Abv)); + Abv = std::make_shared<llvm::BitCodeAbbrev>(); + Abv->Add(llvm::BitCodeAbbrevOp(UPDATE_TU_LOCAL_VISIBLE)); + Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::VBR, 6)); + Abv->Add(llvm::BitCodeAbbrevOp(llvm::BitCodeAbbrevOp::Blob)); + TULocalUpdateVisibleAbbrev = Stream.EmitAbbrev(std::move(Abv)); + // And a visible updates block for the translation unit. WriteDeclContextVisibleUpdate(Context, TU); diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index 7a494cfe1ac64c..30b28057f4c10f 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -2069,6 +2069,7 @@ void ASTDeclWriter::VisitDeclContext(DeclContext *DC) { uint64_t LexicalOffset = 0; uint64_t VisibleOffset = 0; uint64_t ModuleLocalOffset = 0; + uint64_t TULocalOffset = 0; if (Writer.isGeneratingReducedBMI() && isa<NamespaceDecl>(DC) && cast<NamespaceDecl>(DC)->isFromExplicitGlobalModule()) { @@ -2080,12 +2081,14 @@ void ASTDeclWriter::VisitDeclContext(DeclContext *DC) { LexicalOffset = Writer.WriteDeclContextLexicalBlock(Record.getASTContext(), DC); Writer.WriteDeclContextVisibleBlock(Record.getASTContext(), DC, - VisibleOffset, ModuleLocalOffset); + VisibleOffset, ModuleLocalOffset, + TULocalOffset); } Record.AddOffset(LexicalOffset); Record.AddOffset(VisibleOffset); Record.AddOffset(ModuleLocalOffset); + Record.AddOffset(TULocalOffset); } const Decl *ASTWriter::getFirstLocalDecl(const Decl *D) { @@ -2441,6 +2444,7 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalOffset Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // VisibleOffset Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ModuleLocalOffset + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TULocalOffset DeclEnumAbbrev = Stream.EmitAbbrev(std::move(Abv)); // Abbreviation for DECL_RECORD @@ -2494,6 +2498,7 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalOffset Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // VisibleOffset Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ModuleLocalOffset + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TULocalOffset DeclRecordAbbrev = Stream.EmitAbbrev(std::move(Abv)); // Abbreviation for DECL_PARM_VAR @@ -2836,6 +2841,11 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); DeclModuleLocalVisibleLookupAbbrev = Stream.EmitAbbrev(std::move(Abv)); + Abv = std::make_shared<BitCodeAbbrev>(); + Abv->Add(BitCodeAbbrevOp(serialization::DECL_CONTEXT_TU_LOCAL_VISIBLE)); + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + DeclTULocalLookupAbbrev = Stream.EmitAbbrev(std::move(Abv)); + Abv = std::make_shared<BitCodeAbbrev>(); Abv->Add(BitCodeAbbrevOp(serialization::DECL_SPECIALIZATIONS)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p5-ex2.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p5-ex2.cpp index a27946bd90a46c..c200abafc0af82 100644 --- a/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p5-ex2.cpp +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.argdep/p5-ex2.cpp @@ -61,6 +61,6 @@ void test() { // error: S::f is visible in instantiation context, but R::g has internal // linkage and cannot be used outside N.cpp - apply(x, S::Z()); // expected-er...@n.cpp:10 {{no matching function for call to 'g'}} - // expected-note@-1 {{in instantiation of function template specialization 'apply<R::X, S::Z>' requested here}} + apply(x, S::Z()); // expected-er...@n.cpp:10 {{use of undeclared identifier 'g'}} + // expected-note@-1 {{requested here}} } diff --git a/clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp b/clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp index 54ec6aa61ec37b..d70eb7de22c6a1 100644 --- a/clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp +++ b/clang/test/CXX/basic/basic.scope/basic.scope.namespace/p2.cpp @@ -66,11 +66,7 @@ void test_late() { // expected-n...@p2.cpp:18 {{'exported' declared here}} #endif - internal = 1; -#ifndef IMPLEMENTATION - // expected-error@-2 {{declaration of 'internal' must be imported from module 'A' before it is required}} - // expected-n...@p2.cpp:20 {{declaration here is not visible}} -#endif + internal = 1; // expected-error {{use of undeclared identifier 'internal'}} not_exported_private = 1; #ifndef IMPLEMENTATION @@ -78,11 +74,7 @@ void test_late() { // expected-error@-3 {{undeclared identifier}} #endif - internal_private = 1; -#ifndef IMPLEMENTATION - // FIXME: should not be visible here - // expected-error@-3 {{undeclared identifier}} -#endif + internal_private = 1; // expected-error {{use of undeclared identifier 'internal_private'}} } #endif diff --git a/clang/test/CXX/module/basic/basic.def.odr/p4.cppm b/clang/test/CXX/module/basic/basic.def.odr/p4.cppm index 487dbdef283eeb..7e88cbe78b4e37 100644 --- a/clang/test/CXX/module/basic/basic.def.odr/p4.cppm +++ b/clang/test/CXX/module/basic/basic.def.odr/p4.cppm @@ -128,7 +128,6 @@ void f(a::b, a::c) {} // // CHECK-DAG: @_ZW6Module25extern_var_module_linkage = external {{(dso_local )?}}global // CHECK-DAG: @_ZW6Module25inline_var_module_linkage = linkonce_odr {{(dso_local )?}}global -// CHECK-DAG: @_ZL25static_var_module_linkage = internal {{(dso_local )?}}global i32 0, // CHECK-DAG: @_ZW6Module24const_var_module_linkage = available_externally {{(dso_local )?}}constant i32 3, module Module; @@ -152,10 +151,6 @@ void use() { (void)&extern_var_module_linkage; (void)&inline_var_module_linkage; - // FIXME: Issue #61427 Internal-linkage declarations in the interface TU - // should not be not visible here. - (void)&static_var_module_linkage; // FIXME: Should not be visible here. - (void)&const_var_module_linkage; // FIXME: will be visible after P2788R0 } diff --git a/clang/test/CXX/module/basic/basic.link/p2.cppm b/clang/test/CXX/module/basic/basic.link/p2.cppm index 5a497304201dce..d7d2b5992a2353 100644 --- a/clang/test/CXX/module/basic/basic.link/p2.cppm +++ b/clang/test/CXX/module/basic/basic.link/p2.cppm @@ -45,16 +45,14 @@ module M; void use_from_module_impl() { external_linkage_fn(); module_linkage_fn(); - internal_linkage_fn(); // expected-error {{no matching function for call to 'internal_linkage_fn'}} + internal_linkage_fn(); // expected-error {{use of undeclared identifier 'internal_linkage_fn'}} // expected-note@* {{}} (void)external_linkage_class{}; (void)module_linkage_class{}; (void)external_linkage_var; (void)module_linkage_var; - // FIXME: Issue #61427 Internal-linkage declarations in the interface TU - // should not be not visible here. - (void)internal_linkage_class{}; - (void)internal_linkage_var; + (void)internal_linkage_class{}; // expected-error {{use of undeclared identifier 'internal_linkage_class'}} //expected-error{{}} + (void)internal_linkage_var; // expected-error {{use of undeclared identifier 'internal_linkage_var'}} } //--- user.cpp @@ -63,11 +61,10 @@ import M; void use_from_module_impl() { external_linkage_fn(); module_linkage_fn(); // expected-error {{use of undeclared identifier 'module_linkage_fn'}} - internal_linkage_fn(); // expected-error {{declaration of 'internal_linkage_fn' must be imported}} + internal_linkage_fn(); // expected-error {{use of undeclared identifier 'internal_linkage_fn'}} (void)external_linkage_class{}; - (void)module_linkage_class{}; // expected-error {{undeclared identifier}} expected-error 0+{{}} + (void)module_linkage_class{}; // expected-error {{undeclared identifier}} expected-error 0+{{}} // expected-note@* {{}} (void)internal_linkage_class{}; // expected-error {{undeclared identifier}} expected-error 0+{{}} - // expected-n...@m.cppm:10 {{declaration here is not visible}} (void)external_linkage_var; (void)module_linkage_var; // expected-error {{undeclared identifier}} (void)internal_linkage_var; // expected-error {{undeclared identifier}} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits