Skip to content

Commit 4915fdd

Browse files
authored
[Serialization] Add a callback to register new created predefined decls for DeserializationListener (#102855)
Close #102684 The root cause of the issue is, it is possible that the predefined decl is not registered at the beginning of writing a module file but got created during the process of writing from reading. This is incorrect. The predefined decls should always be predefined decls. Another deep thought about the issue is, we shouldn't read any new things after we start to write the module file. But this is another deeper question.
1 parent a0241e7 commit 4915fdd

File tree

8 files changed

+129
-18
lines changed

8 files changed

+129
-18
lines changed

clang/include/clang/Frontend/MultiplexConsumer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class MultiplexASTDeserializationListener : public ASTDeserializationListener {
3636
void MacroRead(serialization::MacroID ID, MacroInfo *MI) override;
3737
void TypeRead(serialization::TypeIdx Idx, QualType T) override;
3838
void DeclRead(GlobalDeclID ID, const Decl *D) override;
39+
void PredefinedDeclBuilt(PredefinedDeclIDs ID, const Decl *D) override;
3940
void SelectorRead(serialization::SelectorID iD, Selector Sel) override;
4041
void MacroDefinitionRead(serialization::PreprocessedEntityID,
4142
MacroDefinitionRecord *MD) override;

clang/include/clang/Serialization/ASTDeserializationListener.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ class ASTDeserializationListener {
4545
virtual void TypeRead(serialization::TypeIdx Idx, QualType T) { }
4646
/// A decl was deserialized from the AST file.
4747
virtual void DeclRead(GlobalDeclID ID, const Decl *D) {}
48+
/// A predefined decl was built during the serialization.
49+
virtual void PredefinedDeclBuilt(PredefinedDeclIDs ID, const Decl *D) {}
4850
/// A selector was read from the AST file.
4951
virtual void SelectorRead(serialization::SelectorID iD, Selector Sel) {}
5052
/// A macro definition was read from the AST file.

clang/include/clang/Serialization/ASTReader.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1559,6 +1559,9 @@ class ASTReader
15591559
std::pair<ModuleFile *, unsigned>
15601560
translateTypeIDToIndex(serialization::TypeID ID) const;
15611561

1562+
/// Get a predefined Decl from ASTContext.
1563+
Decl *getPredefinedDecl(PredefinedDeclIDs ID);
1564+
15621565
public:
15631566
/// Load the AST file and validate its contents against the given
15641567
/// Preprocessor.

clang/include/clang/Serialization/ASTWriter.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -869,6 +869,7 @@ class ASTWriter : public ASTDeserializationListener,
869869
void IdentifierRead(serialization::IdentifierID ID, IdentifierInfo *II) override;
870870
void MacroRead(serialization::MacroID ID, MacroInfo *MI) override;
871871
void TypeRead(serialization::TypeIdx Idx, QualType T) override;
872+
void PredefinedDeclBuilt(PredefinedDeclIDs ID, const Decl *D) override;
872873
void SelectorRead(serialization::SelectorID ID, Selector Sel) override;
873874
void MacroDefinitionRead(serialization::PreprocessedEntityID ID,
874875
MacroDefinitionRecord *MD) override;

clang/lib/Frontend/MultiplexConsumer.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ void MultiplexASTDeserializationListener::DeclRead(GlobalDeclID ID,
5858
Listeners[i]->DeclRead(ID, D);
5959
}
6060

61+
void MultiplexASTDeserializationListener::PredefinedDeclBuilt(PredefinedDeclIDs ID, const Decl *D) {
62+
for (size_t i = 0, e = Listeners.size(); i != e; ++i)
63+
Listeners[i]->PredefinedDeclBuilt(ID, D);
64+
}
65+
6166
void MultiplexASTDeserializationListener::SelectorRead(
6267
serialization::SelectorID ID, Selector Sel) {
6368
for (size_t i = 0, e = Listeners.size(); i != e; ++i)

clang/lib/Serialization/ASTReader.cpp

Lines changed: 73 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7787,7 +7787,10 @@ SourceLocation ASTReader::getSourceLocationForDeclID(GlobalDeclID ID) {
77877787
return Loc;
77887788
}
77897789

7790-
static Decl *getPredefinedDecl(ASTContext &Context, PredefinedDeclIDs ID) {
7790+
Decl *ASTReader::getPredefinedDecl(PredefinedDeclIDs ID) {
7791+
assert(ContextObj && "reading predefined decl without AST context");
7792+
ASTContext &Context = *ContextObj;
7793+
Decl *NewLoaded = nullptr;
77917794
switch (ID) {
77927795
case PREDEF_DECL_NULL_ID:
77937796
return nullptr;
@@ -7796,54 +7799,106 @@ static Decl *getPredefinedDecl(ASTContext &Context, PredefinedDeclIDs ID) {
77967799
return Context.getTranslationUnitDecl();
77977800

77987801
case PREDEF_DECL_OBJC_ID_ID:
7799-
return Context.getObjCIdDecl();
7802+
if (Context.ObjCIdDecl)
7803+
return Context.ObjCIdDecl;
7804+
NewLoaded = Context.getObjCIdDecl();
7805+
break;
78007806

78017807
case PREDEF_DECL_OBJC_SEL_ID:
7802-
return Context.getObjCSelDecl();
7808+
if (Context.ObjCSelDecl)
7809+
return Context.ObjCSelDecl;
7810+
NewLoaded = Context.getObjCSelDecl();
7811+
break;
78037812

78047813
case PREDEF_DECL_OBJC_CLASS_ID:
7805-
return Context.getObjCClassDecl();
7814+
if (Context.ObjCClassDecl)
7815+
return Context.ObjCClassDecl;
7816+
NewLoaded = Context.getObjCClassDecl();
7817+
break;
78067818

78077819
case PREDEF_DECL_OBJC_PROTOCOL_ID:
7808-
return Context.getObjCProtocolDecl();
7820+
if (Context.ObjCProtocolClassDecl)
7821+
return Context.ObjCProtocolClassDecl;
7822+
NewLoaded = Context.getObjCProtocolDecl();
7823+
break;
78097824

78107825
case PREDEF_DECL_INT_128_ID:
7811-
return Context.getInt128Decl();
7826+
if (Context.Int128Decl)
7827+
return Context.Int128Decl;
7828+
NewLoaded = Context.getInt128Decl();
7829+
break;
78127830

78137831
case PREDEF_DECL_UNSIGNED_INT_128_ID:
7814-
return Context.getUInt128Decl();
7832+
if (Context.UInt128Decl)
7833+
return Context.UInt128Decl;
7834+
NewLoaded = Context.getUInt128Decl();
7835+
break;
78157836

78167837
case PREDEF_DECL_OBJC_INSTANCETYPE_ID:
7817-
return Context.getObjCInstanceTypeDecl();
7838+
if (Context.ObjCInstanceTypeDecl)
7839+
return Context.ObjCInstanceTypeDecl;
7840+
NewLoaded = Context.getObjCInstanceTypeDecl();
7841+
break;
78187842

78197843
case PREDEF_DECL_BUILTIN_VA_LIST_ID:
7820-
return Context.getBuiltinVaListDecl();
7844+
if (Context.BuiltinVaListDecl)
7845+
return Context.BuiltinVaListDecl;
7846+
NewLoaded = Context.getBuiltinVaListDecl();
7847+
break;
78217848

78227849
case PREDEF_DECL_VA_LIST_TAG:
7823-
return Context.getVaListTagDecl();
7850+
if (Context.VaListTagDecl)
7851+
return Context.VaListTagDecl;
7852+
NewLoaded = Context.getVaListTagDecl();
7853+
break;
78247854

78257855
case PREDEF_DECL_BUILTIN_MS_VA_LIST_ID:
7826-
return Context.getBuiltinMSVaListDecl();
7856+
if (Context.BuiltinMSVaListDecl)
7857+
return Context.BuiltinMSVaListDecl;
7858+
NewLoaded = Context.getBuiltinMSVaListDecl();
7859+
break;
78277860

78287861
case PREDEF_DECL_BUILTIN_MS_GUID_ID:
7862+
// ASTContext::getMSGuidTagDecl won't create MSGuidTagDecl conditionally.
78297863
return Context.getMSGuidTagDecl();
78307864

78317865
case PREDEF_DECL_EXTERN_C_CONTEXT_ID:
7832-
return Context.getExternCContextDecl();
7866+
if (Context.ExternCContext)
7867+
return Context.ExternCContext;
7868+
NewLoaded = Context.getExternCContextDecl();
7869+
break;
78337870

78347871
case PREDEF_DECL_MAKE_INTEGER_SEQ_ID:
7835-
return Context.getMakeIntegerSeqDecl();
7872+
if (Context.MakeIntegerSeqDecl)
7873+
return Context.MakeIntegerSeqDecl;
7874+
NewLoaded = Context.getMakeIntegerSeqDecl();
7875+
break;
78367876

78377877
case PREDEF_DECL_CF_CONSTANT_STRING_ID:
7838-
return Context.getCFConstantStringDecl();
7878+
if (Context.CFConstantStringTypeDecl)
7879+
return Context.CFConstantStringTypeDecl;
7880+
NewLoaded = Context.getCFConstantStringDecl();
7881+
break;
78397882

78407883
case PREDEF_DECL_CF_CONSTANT_STRING_TAG_ID:
7841-
return Context.getCFConstantStringTagDecl();
7884+
if (Context.CFConstantStringTagDecl)
7885+
return Context.CFConstantStringTagDecl;
7886+
NewLoaded = Context.getCFConstantStringTagDecl();
7887+
break;
78427888

78437889
case PREDEF_DECL_TYPE_PACK_ELEMENT_ID:
7844-
return Context.getTypePackElementDecl();
7890+
if (Context.TypePackElementDecl)
7891+
return Context.TypePackElementDecl;
7892+
NewLoaded = Context.getTypePackElementDecl();
7893+
break;
78457894
}
7846-
llvm_unreachable("PredefinedDeclIDs unknown enum value");
7895+
7896+
assert(NewLoaded && "Failed to load predefined decl?");
7897+
7898+
if (DeserializationListener)
7899+
DeserializationListener->PredefinedDeclBuilt(ID, NewLoaded);
7900+
7901+
return NewLoaded;
78477902
}
78487903

78497904
unsigned ASTReader::translateGlobalDeclIDToIndex(GlobalDeclID GlobalID) const {
@@ -7860,7 +7915,7 @@ Decl *ASTReader::GetExistingDecl(GlobalDeclID ID) {
78607915
assert(ContextObj && "reading decl with no AST context");
78617916

78627917
if (ID < NUM_PREDEF_DECL_IDS) {
7863-
Decl *D = getPredefinedDecl(*ContextObj, (PredefinedDeclIDs)ID);
7918+
Decl *D = getPredefinedDecl((PredefinedDeclIDs)ID);
78647919
if (D) {
78657920
// Track that we have merged the declaration with ID \p ID into the
78667921
// pre-existing predefined declaration \p D.

clang/lib/Serialization/ASTWriter.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6754,6 +6754,12 @@ void ASTWriter::TypeRead(TypeIdx Idx, QualType T) {
67546754
StoredIdx = Idx;
67556755
}
67566756

6757+
void ASTWriter::PredefinedDeclBuilt(PredefinedDeclIDs ID, const Decl *D) {
6758+
assert(D->isCanonicalDecl() && "predefined decl is not canonical");
6759+
DeclIDs[D] = LocalDeclID(ID);
6760+
PredefinedDecls.insert(D);
6761+
}
6762+
67576763
void ASTWriter::SelectorRead(SelectorID ID, Selector S) {
67586764
// Always keep the highest ID. See \p TypeRead() for more information.
67596765
SelectorID &StoredID = SelectorIDs[S];

clang/test/Modules/pr102684.cppm

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// RUN: rm -rf %t
2+
// RUN: mkdir -p %t
3+
// RUN: split-file %s %t
4+
//
5+
// RUN: %clang_cc1 -std=c++20 %t/a.cppm -emit-module-interface -o %t/a.pcm
6+
// RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-module-interface -o %t/b.pcm \
7+
// RUN: -fprebuilt-module-path=%t
8+
// RUN: %clang_cc1 -std=c++20 %t/test.cpp -fsyntax-only -verify \
9+
// RUN: -fprebuilt-module-path=%t
10+
11+
//--- a.cppm
12+
export module a;
13+
14+
namespace n {
15+
template<typename, int...>
16+
struct integer_sequence {
17+
18+
};
19+
20+
export template<typename>
21+
using make_integer_sequence = __make_integer_seq<integer_sequence, int, 0>;
22+
}
23+
24+
//--- b.cppm
25+
export module b;
26+
import a;
27+
28+
export template<typename T>
29+
void b() {
30+
n::make_integer_sequence<T>();
31+
}
32+
33+
//--- test.cpp
34+
// expected-no-diagnostics
35+
import b;
36+
void test() {
37+
b<int>();
38+
}

0 commit comments

Comments
 (0)