Skip to content

Commit d957da8

Browse files
committed
[clang][Interp] Allow taking the address of a non-const global reference
This is not a read, but the GetGlobal op before failed if the reference we were taking a pointer of was non-const. Use GetGlobalUnchecked instead.
1 parent 540fd42 commit d957da8

File tree

3 files changed

+14
-3
lines changed

3 files changed

+14
-3
lines changed

clang/lib/AST/Interp/Compiler.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4906,8 +4906,11 @@ bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
49064906
return this->emitGetLocal(PT_Ptr, Offset, E);
49074907
return this->emitGetPtrLocal(Offset, E);
49084908
} else if (auto GlobalIndex = P.getGlobal(D)) {
4909-
if (IsReference)
4910-
return this->emitGetGlobal(classifyPrim(E), *GlobalIndex, E);
4909+
if (IsReference) {
4910+
if (!Ctx.getLangOpts().CPlusPlus11)
4911+
return this->emitGetGlobal(classifyPrim(E), *GlobalIndex, E);
4912+
return this->emitGetGlobalUnchecked(classifyPrim(E), *GlobalIndex, E);
4913+
}
49114914

49124915
return this->emitGetPtrGlobal(*GlobalIndex, E);
49134916
} else if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) {

clang/lib/AST/Interp/Interp.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1255,7 +1255,10 @@ bool GetGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
12551255
/// Same as GetGlobal, but without the checks.
12561256
template <PrimType Name, class T = typename PrimConv<Name>::T>
12571257
bool GetGlobalUnchecked(InterpState &S, CodePtr OpPC, uint32_t I) {
1258-
auto *B = S.P.getGlobal(I);
1258+
const Pointer &Ptr = S.P.getPtrGlobal(I);
1259+
if (!Ptr.isInitialized())
1260+
return false;
1261+
const Block *B = S.P.getGlobal(I);
12591262
S.Stk.push<T>(B->deref<T>());
12601263
return true;
12611264
}

clang/test/AST/Interp/references.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,8 @@ const char (&nonextended_string_ref)[3] = {"hi"};
130130
static_assert(nonextended_string_ref[0] == 'h', "");
131131
static_assert(nonextended_string_ref[1] == 'i', "");
132132
static_assert(nonextended_string_ref[2] == '\0', "");
133+
134+
/// This isa non-constant context. Reading A is not allowed,
135+
/// but taking its address is.
136+
int &&A = 12;
137+
int arr[!&A];

0 commit comments

Comments
 (0)