Skip to content

Commit 37eb465

Browse files
authored
Reland "[Modules] Record whether VarDecl initializers contain side effects" (#145447)
This reverts commit 329ae86 and adds an early exit for EvaluateInPlace when the expression's type is null.
1 parent 0fcced7 commit 37eb465

File tree

12 files changed

+122
-9
lines changed

12 files changed

+122
-9
lines changed

clang/include/clang/AST/Decl.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1352,6 +1352,11 @@ class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
13521352
return const_cast<VarDecl *>(this)->getInitializingDeclaration();
13531353
}
13541354

1355+
/// Checks whether this declaration has an initializer with side effects,
1356+
/// without triggering deserialization if the initializer is not yet
1357+
/// deserialized.
1358+
bool hasInitWithSideEffects() const;
1359+
13551360
/// Determine whether this variable's value might be usable in a
13561361
/// constant expression, according to the relevant language standard.
13571362
/// This only checks properties of the declaration, and does not check

clang/include/clang/AST/ExternalASTSource.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class RecordDecl;
5151
class Selector;
5252
class Stmt;
5353
class TagDecl;
54+
class VarDecl;
5455

5556
/// Abstract interface for external sources of AST nodes.
5657
///
@@ -195,6 +196,10 @@ class ExternalASTSource : public RefCountedBase<ExternalASTSource> {
195196
/// module.
196197
virtual bool wasThisDeclarationADefinition(const FunctionDecl *FD);
197198

199+
virtual bool hasInitializerWithSideEffects(const VarDecl *VD) const {
200+
return false;
201+
}
202+
198203
/// Finds all declarations lexically contained within the given
199204
/// DeclContext, after applying an optional filter predicate.
200205
///
@@ -429,6 +434,17 @@ struct LazyOffsetPtr {
429434
return GetPtr();
430435
}
431436

437+
/// Retrieve the pointer to the AST node that this lazy pointer points to,
438+
/// if it can be done without triggering deserialization.
439+
///
440+
/// \returns a pointer to the AST node, or null if not yet deserialized.
441+
T *getWithoutDeserializing() const {
442+
if (isOffset()) {
443+
return nullptr;
444+
}
445+
return GetPtr();
446+
}
447+
432448
/// Retrieve the address of the AST node pointer. Deserializes the pointee if
433449
/// necessary.
434450
T **getAddressOfPointer(ExternalASTSource *Source) const {

clang/include/clang/Sema/MultiplexExternalSemaSource.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ class MultiplexExternalSemaSource : public ExternalSemaSource {
9494

9595
bool wasThisDeclarationADefinition(const FunctionDecl *FD) override;
9696

97+
bool hasInitializerWithSideEffects(const VarDecl *VD) const override;
98+
9799
/// Find all declarations with the given name in the
98100
/// given context.
99101
bool FindExternalVisibleDeclsByName(const DeclContext *DC,

clang/include/clang/Serialization/ASTReader.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1455,6 +1455,12 @@ class ASTReader
14551455
const StringRef &operator*() && = delete;
14561456
};
14571457

1458+
/// VarDecls with initializers containing side effects must be emitted,
1459+
/// but DeclMustBeEmitted is not allowed to deserialize the intializer.
1460+
/// FIXME: Lower memory usage by removing VarDecls once the initializer
1461+
/// is deserialized.
1462+
llvm::SmallPtrSet<Decl *, 16> InitSideEffectVars;
1463+
14581464
public:
14591465
/// Get the buffer for resolving paths.
14601466
SmallString<0> &getPathBuf() { return PathBuf; }
@@ -2406,6 +2412,8 @@ class ASTReader
24062412

24072413
bool wasThisDeclarationADefinition(const FunctionDecl *FD) override;
24082414

2415+
bool hasInitializerWithSideEffects(const VarDecl *VD) const override;
2416+
24092417
/// Retrieve a selector from the given module with its local ID
24102418
/// number.
24112419
Selector getLocalSelector(ModuleFile &M, unsigned LocalID);

clang/lib/AST/ASTContext.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13110,9 +13110,7 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
1311013110
return true;
1311113111

1311213112
// Variables that have initialization with side-effects are required.
13113-
if (VD->getInit() && VD->getInit()->HasSideEffects(*this) &&
13114-
// We can get a value-dependent initializer during error recovery.
13115-
(VD->getInit()->isValueDependent() || !VD->evaluateValue()))
13113+
if (VD->hasInitWithSideEffects())
1311613114
return true;
1311713115

1311813116
// Likewise, variables with tuple-like bindings are required if their

clang/lib/AST/Decl.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2441,6 +2441,30 @@ VarDecl *VarDecl::getInitializingDeclaration() {
24412441
return Def;
24422442
}
24432443

2444+
bool VarDecl::hasInitWithSideEffects() const {
2445+
if (!hasInit())
2446+
return false;
2447+
2448+
// Check if we can get the initializer without deserializing
2449+
const Expr *E = nullptr;
2450+
if (auto *S = dyn_cast<Stmt *>(Init)) {
2451+
E = cast<Expr>(S);
2452+
} else {
2453+
E = cast_or_null<Expr>(getEvaluatedStmt()->Value.getWithoutDeserializing());
2454+
}
2455+
2456+
if (E)
2457+
return E->HasSideEffects(getASTContext()) &&
2458+
// We can get a value-dependent initializer during error recovery.
2459+
(E->isValueDependent() || !evaluateValue());
2460+
2461+
assert(getEvaluatedStmt()->Value.isOffset());
2462+
// ASTReader tracks this without having to deserialize the initializer
2463+
if (auto Source = getASTContext().getExternalSource())
2464+
return Source->hasInitializerWithSideEffects(this);
2465+
return false;
2466+
}
2467+
24442468
bool VarDecl::isOutOfLine() const {
24452469
if (Decl::isOutOfLine())
24462470
return true;

clang/lib/AST/ExprConstant.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16719,6 +16719,12 @@ static bool EvaluateInPlace(APValue &Result, EvalInfo &Info, const LValue &This,
1671916719
const Expr *E, bool AllowNonLiteralTypes) {
1672016720
assert(!E->isValueDependent());
1672116721

16722+
// Normally expressions passed to EvaluateInPlace have a type, but not when
16723+
// a VarDecl initializer is evaluated before the untyped ParenListExpr is
16724+
// replaced with a CXXConstructExpr. This can happen in LLDB.
16725+
if (E->getType().isNull())
16726+
return false;
16727+
1672216728
if (!AllowNonLiteralTypes && !CheckLiteralType(Info, E, &This))
1672316729
return false;
1672416730

clang/lib/Sema/MultiplexExternalSemaSource.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,14 @@ bool MultiplexExternalSemaSource::wasThisDeclarationADefinition(
115115
return false;
116116
}
117117

118+
bool MultiplexExternalSemaSource::hasInitializerWithSideEffects(
119+
const VarDecl *VD) const {
120+
for (const auto &S : Sources)
121+
if (S->hasInitializerWithSideEffects(VD))
122+
return true;
123+
return false;
124+
}
125+
118126
bool MultiplexExternalSemaSource::FindExternalVisibleDeclsByName(
119127
const DeclContext *DC, DeclarationName Name,
120128
const DeclContext *OriginalDC) {

clang/lib/Serialization/ASTReader.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9722,6 +9722,10 @@ bool ASTReader::wasThisDeclarationADefinition(const FunctionDecl *FD) {
97229722
return ThisDeclarationWasADefinitionSet.contains(FD);
97239723
}
97249724

9725+
bool ASTReader::hasInitializerWithSideEffects(const VarDecl *VD) const {
9726+
return InitSideEffectVars.count(VD);
9727+
}
9728+
97259729
Selector ASTReader::getLocalSelector(ModuleFile &M, unsigned LocalID) {
97269730
return DecodeSelector(getGlobalSelectorID(M, LocalID));
97279731
}

clang/lib/Serialization/ASTReaderDecl.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1628,6 +1628,9 @@ RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) {
16281628
VD->NonParmVarDeclBits.PreviousDeclInSameBlockScope =
16291629
VarDeclBits.getNextBit();
16301630

1631+
if (VarDeclBits.getNextBit())
1632+
Reader.InitSideEffectVars.insert(VD);
1633+
16311634
VD->NonParmVarDeclBits.EscapingByref = VarDeclBits.getNextBit();
16321635
HasDeducedType = VarDeclBits.getNextBit();
16331636
VD->NonParmVarDeclBits.ImplicitParamKind =

0 commit comments

Comments
 (0)