Skip to content

Commit e4f3b56

Browse files
authored
[clang][bytecode] Fix diagnosing reads from temporaries (#106868)
Fix the DeclID not being set in global temporaries and use the same strategy for deciding if a temporary is readable as the current interpreter.
1 parent 6f682c2 commit e4f3b56

File tree

3 files changed

+26
-11
lines changed

3 files changed

+26
-11
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3772,7 +3772,6 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD,
37723772

37733773
auto initGlobal = [&](unsigned GlobalIndex) -> bool {
37743774
assert(Init);
3775-
DeclScope<Emitter> LocalScope(this, VD);
37763775

37773776
if (VarT) {
37783777
if (!this->visit(Init))
@@ -3796,6 +3795,8 @@ VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD,
37963795
return this->emitPopPtr(Init);
37973796
};
37983797

3798+
DeclScope<Emitter> LocalScope(this, VD);
3799+
37993800
// We've already seen and initialized this global.
38003801
if (std::optional<unsigned> GlobalIndex = P.getGlobal(VD)) {
38013802
if (P.getPtrGlobal(*GlobalIndex).isInitialized())

clang/lib/AST/ByteCode/Interp.cpp

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -181,16 +181,21 @@ static bool CheckTemporary(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
181181
if (!Ptr.isStaticTemporary())
182182
return true;
183183

184-
if (Ptr.getDeclDesc()->getType().isConstQualified())
184+
const auto *MTE = dyn_cast_if_present<MaterializeTemporaryExpr>(
185+
Ptr.getDeclDesc()->asExpr());
186+
if (!MTE)
185187
return true;
186188

187-
if (S.P.getCurrentDecl() == ID)
188-
return true;
189-
190-
const SourceInfo &E = S.Current->getSource(OpPC);
191-
S.FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK;
192-
S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
193-
return false;
189+
// FIXME(perf): Since we do this check on every Load from a static
190+
// temporary, it might make sense to cache the value of the
191+
// isUsableInConstantExpressions call.
192+
if (!MTE->isUsableInConstantExpressions(S.getASTContext()) &&
193+
Ptr.block()->getEvalID() != S.Ctx.getEvalID()) {
194+
const SourceInfo &E = S.Current->getSource(OpPC);
195+
S.FFDiag(E, diag::note_constexpr_access_static_temporary, 1) << AK;
196+
S.Note(Ptr.getDeclLoc(), diag::note_constexpr_temporary_here);
197+
return false;
198+
}
194199
}
195200
return true;
196201
}

clang/test/AST/ByteCode/references.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify %s
2-
// RUN: %clang_cc1 -verify=ref %s
1+
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=expected,both %s
2+
// RUN: %clang_cc1 -verify=ref,both %s
33

44

55
constexpr int a = 10;
@@ -135,3 +135,12 @@ static_assert(nonextended_string_ref[2] == '\0', "");
135135
/// but taking its address is.
136136
int &&A = 12;
137137
int arr[!&A];
138+
139+
namespace Temporaries {
140+
struct A { int n; };
141+
struct B { const A &a; };
142+
const B j = {{1}}; // both-note {{temporary created here}}
143+
144+
static_assert(j.a.n == 1, ""); // both-error {{not an integral constant expression}} \
145+
// both-note {{read of temporary is not allowed in a constant expression outside the expression that created the temporary}}
146+
}

0 commit comments

Comments
 (0)