aboutsummaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
authorHenrik G. Olsson <hnrklssn@gmail.com>2025-07-03 15:37:55 -0700
committerGitHub <noreply@github.com>2025-07-03 15:37:55 -0700
commit2910c24638fcbc3dec02be072e6026d01012d946 (patch)
treee11a429e6afc5c40e2ee6f1537737d4b3abe1d74 /clang/lib
parent9bfb347ea0a0a260eb505921dfc0cb824a6ced5d (diff)
downloadllvm-2910c24638fcbc3dec02be072e6026d01012d946.zip
llvm-2910c24638fcbc3dec02be072e6026d01012d946.tar.gz
llvm-2910c24638fcbc3dec02be072e6026d01012d946.tar.bz2
[Modules] Record side effect info in EvaluatedStmt (#146468)
All deserialized VarDecl initializers are EvaluatedStmt, but not all EvaluatedStmt initializers are from a PCH. Calling `VarDecl::hasInitWithSideEffects` can trigger constant evaluation, but it's hard to know ahead of time whether that will trigger deserialization - even if the initializer is fully deserialized, it may contain a call to a constructor whose body is not deserialized. By caching the result of `VarDecl::hasInitWithSideEffects` and populating that cache during deserialization we can guarantee that calling it won't trigger deserialization regardless of the state of the initializer. This also reduces memory usage by removing the `InitSideEffectVars` set in `ASTReader`. rdar://154717930
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/Decl.cpp28
-rw-r--r--clang/lib/Sema/MultiplexExternalSemaSource.cpp8
-rw-r--r--clang/lib/Serialization/ASTReader.cpp4
-rw-r--r--clang/lib/Serialization/ASTReaderDecl.cpp5
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp4
-rw-r--r--clang/lib/Serialization/ASTWriterDecl.cpp1
6 files changed, 16 insertions, 34 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 5cdf75d..e036224 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -2444,24 +2444,16 @@ bool VarDecl::hasInitWithSideEffects() const {
if (!hasInit())
return false;
- // Check if we can get the initializer without deserializing
- const Expr *E = nullptr;
- if (auto *S = dyn_cast<Stmt *>(Init)) {
- E = cast<Expr>(S);
- } else {
- E = cast_or_null<Expr>(getEvaluatedStmt()->Value.getWithoutDeserializing());
- }
-
- if (E)
- return E->HasSideEffects(getASTContext()) &&
- // We can get a value-dependent initializer during error recovery.
- (E->isValueDependent() || !evaluateValue());
-
- assert(getEvaluatedStmt()->Value.isOffset());
- // ASTReader tracks this without having to deserialize the initializer
- if (auto Source = getASTContext().getExternalSource())
- return Source->hasInitializerWithSideEffects(this);
- return false;
+ EvaluatedStmt *ES = ensureEvaluatedStmt();
+ if (!ES->CheckedForSideEffects) {
+ const Expr *E = getInit();
+ ES->HasSideEffects =
+ E->HasSideEffects(getASTContext()) &&
+ // We can get a value-dependent initializer during error recovery.
+ (E->isValueDependent() || !evaluateValue());
+ ES->CheckedForSideEffects = true;
+ }
+ return ES->HasSideEffects;
}
bool VarDecl::isOutOfLine() const {
diff --git a/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/clang/lib/Sema/MultiplexExternalSemaSource.cpp
index 9f19f13..fbfb242 100644
--- a/clang/lib/Sema/MultiplexExternalSemaSource.cpp
+++ b/clang/lib/Sema/MultiplexExternalSemaSource.cpp
@@ -115,14 +115,6 @@ bool MultiplexExternalSemaSource::wasThisDeclarationADefinition(
return false;
}
-bool MultiplexExternalSemaSource::hasInitializerWithSideEffects(
- const VarDecl *VD) const {
- for (const auto &S : Sources)
- if (S->hasInitializerWithSideEffects(VD))
- return true;
- return false;
-}
-
bool MultiplexExternalSemaSource::FindExternalVisibleDeclsByName(
const DeclContext *DC, DeclarationName Name,
const DeclContext *OriginalDC) {
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index d42847a..d380afd 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -9733,10 +9733,6 @@ bool ASTReader::wasThisDeclarationADefinition(const FunctionDecl *FD) {
return ThisDeclarationWasADefinitionSet.contains(FD);
}
-bool ASTReader::hasInitializerWithSideEffects(const VarDecl *VD) const {
- return InitSideEffectVars.count(VD);
-}
-
Selector ASTReader::getLocalSelector(ModuleFile &M, unsigned LocalID) {
return DecodeSelector(getGlobalSelectorID(M, LocalID));
}
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 0ffd784..8bde213 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -1628,9 +1628,6 @@ RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) {
VD->NonParmVarDeclBits.PreviousDeclInSameBlockScope =
VarDeclBits.getNextBit();
- if (VarDeclBits.getNextBit())
- Reader.InitSideEffectVars.insert(VD);
-
VD->NonParmVarDeclBits.EscapingByref = VarDeclBits.getNextBit();
HasDeducedType = VarDeclBits.getNextBit();
VD->NonParmVarDeclBits.ImplicitParamKind =
@@ -1701,6 +1698,8 @@ void ASTDeclReader::ReadVarDeclInit(VarDecl *VD) {
Eval->HasConstantInitialization = (Val & 2) != 0;
Eval->HasConstantDestruction = (Val & 4) != 0;
Eval->WasEvaluated = (Val & 8) != 0;
+ Eval->HasSideEffects = (Val & 16) != 0;
+ Eval->CheckedForSideEffects = true;
if (Eval->WasEvaluated) {
Eval->Evaluated = Record.readAPValue();
if (Eval->Evaluated.needsCleanup())
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 874b24b..2bd9ae5 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -7320,6 +7320,10 @@ void ASTRecordWriter::AddVarDeclInit(const VarDecl *VD) {
uint64_t Val = 1;
if (EvaluatedStmt *ES = VD->getEvaluatedStmt()) {
+ // This may trigger evaluation, so run it first
+ if (VD->hasInitWithSideEffects())
+ Val |= 16;
+ assert(ES->CheckedForSideEffects);
Val |= (ES->HasConstantInitialization ? 2 : 0);
Val |= (ES->HasConstantDestruction ? 4 : 0);
APValue *Evaluated = VD->getEvaluatedValue();
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index 7f1b39c..a4474bb 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -1305,7 +1305,6 @@ void ASTDeclWriter::VisitVarDecl(VarDecl *D) {
VarDeclBits.addBit(D->isConstexpr());
VarDeclBits.addBit(D->isInitCapture());
VarDeclBits.addBit(D->isPreviousDeclInSameBlockScope());
- VarDeclBits.addBit(D->hasInitWithSideEffects());
VarDeclBits.addBit(D->isEscapingByref());
HasDeducedType = D->getType()->getContainedDeducedType();