diff options
author | Henrik G. Olsson <hnrklssn@gmail.com> | 2025-07-03 15:37:55 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-07-03 15:37:55 -0700 |
commit | 2910c24638fcbc3dec02be072e6026d01012d946 (patch) | |
tree | e11a429e6afc5c40e2ee6f1537737d4b3abe1d74 /clang/lib | |
parent | 9bfb347ea0a0a260eb505921dfc0cb824a6ced5d (diff) | |
download | llvm-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.cpp | 28 | ||||
-rw-r--r-- | clang/lib/Sema/MultiplexExternalSemaSource.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterDecl.cpp | 1 |
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(); |