Skip to content

Commit 3b29e91

Browse files
committed
[clang][modules] Guard the second part of FinishedDeserializing() to avoid
entering PassInterestingDeclsToConsumer() during FinishedDeserializing().
1 parent 7bb10f4 commit 3b29e91

File tree

4 files changed

+54
-44
lines changed

4 files changed

+54
-44
lines changed

clang/docs/ReleaseNotes.rst

+4-1
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ Improvements to Clang's diagnostics
244244
as function arguments or return value respectively. Note that
245245
:doc:`ThreadSafetyAnalysis` still does not perform alias analysis. The
246246
feature will be default-enabled with ``-Wthread-safety`` in a future release.
247-
- The ``-Wsign-compare`` warning now treats expressions with bitwise not(~) and minus(-) as signed integers
247+
- The ``-Wsign-compare`` warning now treats expressions with bitwise not(~) and minus(-) as signed integers
248248
except for the case where the operand is an unsigned integer
249249
and throws warning if they are compared with unsigned integers (##18878).
250250

@@ -274,6 +274,9 @@ Bug Fixes in This Version
274274
considered an error in C23 mode and are allowed as an extension in earlier language modes.
275275

276276
- Remove the ``static`` specifier for the value of ``_FUNCTION_`` for static functions, in MSVC compatibility mode.
277+
- Fixed a modules crash where exception specifications were not propagated properly (#GH121245, relanded in #GH129982)
278+
- Fixed a problematic case with recursive deserialization within FinishedDeserializing() where
279+
PassInterestingDeclsToConsumer() was called before the declarations were safe to be passed. (#GH129982)
277280

278281
Bug Fixes to Compiler Builtins
279282
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

clang/include/clang/Serialization/ASTReader.h

+4-4
Original file line numberDiff line numberDiff line change
@@ -1176,11 +1176,11 @@ class ASTReader
11761176
/// Number of Decl/types that are currently deserializing.
11771177
unsigned NumCurrentElementsDeserializing = 0;
11781178

1179-
/// Set true while we are in the process of passing deserialized
1180-
/// "interesting" decls to consumer inside FinishedDeserializing().
1181-
/// This is used as a guard to avoid recursively repeating the process of
1179+
/// Set false while we are in a state where we cannot safely pass deserialized
1180+
/// "interesting" decls to the consumer inside FinishedDeserializing().
1181+
/// This is used as a guard to avoid recursively entering the process of
11821182
/// passing decls to consumer.
1183-
bool PassingDeclsToConsumer = false;
1183+
bool CanPassDeclsToConsumer = true;
11841184

11851185
/// The set of identifiers that were read while the AST reader was
11861186
/// (recursively) loading declarations.

clang/lib/Serialization/ASTReader.cpp

+44-37
Original file line numberDiff line numberDiff line change
@@ -10791,47 +10791,54 @@ void ASTReader::FinishedDeserializing() {
1079110791
--NumCurrentElementsDeserializing;
1079210792

1079310793
if (NumCurrentElementsDeserializing == 0) {
10794-
// Propagate exception specification and deduced type updates along
10795-
// redeclaration chains.
10796-
//
10797-
// We do this now rather than in finishPendingActions because we want to
10798-
// be able to walk the complete redeclaration chains of the updated decls.
10799-
while (!PendingExceptionSpecUpdates.empty() ||
10800-
!PendingDeducedTypeUpdates.empty() ||
10801-
!PendingUndeducedFunctionDecls.empty()) {
10802-
auto ESUpdates = std::move(PendingExceptionSpecUpdates);
10803-
PendingExceptionSpecUpdates.clear();
10804-
for (auto Update : ESUpdates) {
10805-
ProcessingUpdatesRAIIObj ProcessingUpdates(*this);
10806-
auto *FPT = Update.second->getType()->castAs<FunctionProtoType>();
10807-
auto ESI = FPT->getExtProtoInfo().ExceptionSpec;
10808-
if (auto *Listener = getContext().getASTMutationListener())
10809-
Listener->ResolvedExceptionSpec(cast<FunctionDecl>(Update.second));
10810-
for (auto *Redecl : Update.second->redecls())
10811-
getContext().adjustExceptionSpec(cast<FunctionDecl>(Redecl), ESI);
10812-
}
10794+
{
10795+
// Guard variable to avoid recursively entering the process of passing
10796+
// decls to consumer.
10797+
SaveAndRestore GuardPassingDeclsToConsumer(CanPassDeclsToConsumer, false);
1081310798

10814-
auto DTUpdates = std::move(PendingDeducedTypeUpdates);
10815-
PendingDeducedTypeUpdates.clear();
10816-
for (auto Update : DTUpdates) {
10817-
ProcessingUpdatesRAIIObj ProcessingUpdates(*this);
10818-
// FIXME: If the return type is already deduced, check that it matches.
10819-
getContext().adjustDeducedFunctionResultType(Update.first,
10820-
Update.second);
10821-
}
10799+
// Propagate exception specification and deduced type updates along
10800+
// redeclaration chains.
10801+
//
10802+
// We do this now rather than in finishPendingActions because we want to
10803+
// be able to walk the complete redeclaration chains of the updated decls.
10804+
while (!PendingExceptionSpecUpdates.empty() ||
10805+
!PendingDeducedTypeUpdates.empty() ||
10806+
!PendingUndeducedFunctionDecls.empty()) {
10807+
auto ESUpdates = std::move(PendingExceptionSpecUpdates);
10808+
PendingExceptionSpecUpdates.clear();
10809+
for (auto Update : ESUpdates) {
10810+
ProcessingUpdatesRAIIObj ProcessingUpdates(*this);
10811+
auto *FPT = Update.second->getType()->castAs<FunctionProtoType>();
10812+
auto ESI = FPT->getExtProtoInfo().ExceptionSpec;
10813+
if (auto *Listener = getContext().getASTMutationListener())
10814+
Listener->ResolvedExceptionSpec(cast<FunctionDecl>(Update.second));
10815+
for (auto *Redecl : Update.second->redecls())
10816+
getContext().adjustExceptionSpec(cast<FunctionDecl>(Redecl), ESI);
10817+
}
1082210818

10823-
auto UDTUpdates = std::move(PendingUndeducedFunctionDecls);
10824-
PendingUndeducedFunctionDecls.clear();
10825-
// We hope we can find the deduced type for the functions by iterating
10826-
// redeclarations in other modules.
10827-
for (FunctionDecl *UndeducedFD : UDTUpdates)
10828-
(void)UndeducedFD->getMostRecentDecl();
10829-
}
10819+
auto DTUpdates = std::move(PendingDeducedTypeUpdates);
10820+
PendingDeducedTypeUpdates.clear();
10821+
for (auto Update : DTUpdates) {
10822+
ProcessingUpdatesRAIIObj ProcessingUpdates(*this);
10823+
// FIXME: If the return type is already deduced, check that it
10824+
// matches.
10825+
getContext().adjustDeducedFunctionResultType(Update.first,
10826+
Update.second);
10827+
}
1083010828

10831-
if (ReadTimer)
10832-
ReadTimer->stopTimer();
10829+
auto UDTUpdates = std::move(PendingUndeducedFunctionDecls);
10830+
PendingUndeducedFunctionDecls.clear();
10831+
// We hope we can find the deduced type for the functions by iterating
10832+
// redeclarations in other modules.
10833+
for (FunctionDecl *UndeducedFD : UDTUpdates)
10834+
(void)UndeducedFD->getMostRecentDecl();
10835+
}
1083310836

10834-
diagnoseOdrViolations();
10837+
if (ReadTimer)
10838+
ReadTimer->stopTimer();
10839+
10840+
diagnoseOdrViolations();
10841+
}
1083510842

1083610843
// We are not in recursive loading, so it's safe to pass the "interesting"
1083710844
// decls to the consumer.

clang/lib/Serialization/ASTReaderDecl.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -4309,12 +4309,12 @@ Decl *ASTReader::ReadDeclRecord(GlobalDeclID ID) {
43094309
void ASTReader::PassInterestingDeclsToConsumer() {
43104310
assert(Consumer);
43114311

4312-
if (PassingDeclsToConsumer)
4312+
if (!CanPassDeclsToConsumer)
43134313
return;
43144314

43154315
// Guard variable to avoid recursively redoing the process of passing
43164316
// decls to consumer.
4317-
SaveAndRestore GuardPassingDeclsToConsumer(PassingDeclsToConsumer, true);
4317+
SaveAndRestore GuardPassingDeclsToConsumer(CanPassDeclsToConsumer, false);
43184318

43194319
// Ensure that we've loaded all potentially-interesting declarations
43204320
// that need to be eagerly loaded.

0 commit comments

Comments
 (0)