[clang] [C++20] [Modules] Makes sure internal declaration won't be found by other TU (PR #123059)
Chuanqi Xu via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 15 06:02:43 PST 2025
https://github.com/ChuanqiXu9 created https://github.com/llvm/llvm-project/pull/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.
>From 8ab290b840c07cfb225d24fa2a048866cfb98160 Mon Sep 17 00:00:00 2001
From: Chuanqi Xu <yedeng.yd at linux.alibaba.com>
Date: Wed, 15 Jan 2025 11:33:54 +0800
Subject: [PATCH] [C++20] [Modules] Makes sure internal declaration won't be
found by other TU
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.
---
.../include/clang/Serialization/ASTBitCodes.h | 6 +
clang/include/clang/Serialization/ASTReader.h | 20 +-
clang/include/clang/Serialization/ASTWriter.h | 11 +-
clang/lib/Serialization/ASTReader.cpp | 89 ++++++--
clang/lib/Serialization/ASTReaderDecl.cpp | 45 +++-
clang/lib/Serialization/ASTWriter.cpp | 216 +++++++++++++-----
clang/lib/Serialization/ASTWriterDecl.cpp | 12 +-
.../basic.lookup.argdep/p5-ex2.cpp | 4 +-
.../basic.scope/basic.scope.namespace/p2.cpp | 12 +-
.../CXX/module/basic/basic.def.odr/p4.cppm | 5 -
.../test/CXX/module/basic/basic.link/p2.cppm | 13 +-
11 files changed, 318 insertions(+), 115 deletions(-)
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 ea12adaec3ee81..1459c9f9b083f1 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;
@@ -1463,6 +1478,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 06853a227215e0..b1d79727603163 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 "
@@ -8471,6 +8509,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();
}
@@ -8498,6 +8545,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);
@@ -8517,6 +8565,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());
@@ -8632,6 +8686,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 1c51a7b5e460f6..72191395ec8067 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>
@@ -3875,6 +3880,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");
@@ -4185,9 +4191,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.
@@ -4199,18 +4206,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());
@@ -4376,6 +4389,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 a6f8c6009f1ffa..d405ca26902439 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -4044,6 +4044,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(
@@ -4136,23 +4143,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) {
@@ -4181,19 +4181,37 @@ class ModuleLocalNameLookupTrait : public ASTDeclContextNameLookupTraitBase {
}
};
+static bool shouldBeInTULocalLookupTable(NamedDecl *D) {
+ Module *NamedModule = D->getTopLevelOwningNamedModule();
+ if (!NamedModule)
+ return false;
+
+ // It is fine enough to not put these in TULocalLookupTable.
+ // Otherwise, if the consumers get its context decl somehow,
+ // it is problematic to lookup in that context.
+ 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) {}
@@ -4229,15 +4247,30 @@ class ASTDeclContextNameLookupTrait : public ASTDeclContextNameLookupTraitBase {
}
}
+ if constexpr (CollectingTULocalDecls) {
+ if (shouldBeInTULocalLookupTable(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(); }
@@ -4465,7 +4498,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");
@@ -4475,9 +4509,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
@@ -4649,26 +4685,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
@@ -4679,7 +4734,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.
@@ -4766,7 +4826,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};
@@ -4774,17 +4836,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.
@@ -4802,7 +4873,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.
@@ -4814,14 +4887,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.
@@ -6004,9 +6083,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();
@@ -6085,7 +6167,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)
@@ -6097,10 +6181,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
@@ -6186,6 +6274,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-error at N.cpp:10 {{no matching function for call to 'g'}}
- // expected-note at -1 {{in instantiation of function template specialization 'apply<R::X, S::Z>' requested here}}
+ apply(x, S::Z()); // expected-error at N.cpp:10 {{use of undeclared identifier 'g'}}
+ // expected-note at -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-note at p2.cpp:18 {{'exported' declared here}}
#endif
- internal = 1;
-#ifndef IMPLEMENTATION
- // expected-error at -2 {{declaration of 'internal' must be imported from module 'A' before it is required}}
- // expected-note at 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 at -3 {{undeclared identifier}}
#endif
- internal_private = 1;
-#ifndef IMPLEMENTATION
- // FIXME: should not be visible here
- // expected-error at -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-note at 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}}
More information about the cfe-commits
mailing list