Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 29 additions & 10 deletions clang/lib/AST/ByteCode/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -2127,19 +2127,28 @@ bool InitElem(InterpState &S, CodePtr OpPC, uint32_t Idx) {
if (Ptr.isUnknownSizeArray())
return false;

const Descriptor *Desc = Ptr.getFieldDesc();
// In the unlikely event that we're initializing the first item of
// a non-array, skip the atIndex().
if (Idx == 0 && !Ptr.getFieldDesc()->isArray()) {
if (Idx == 0 && !Desc->isArray()) {
Ptr.initialize();
new (&Ptr.deref<T>()) T(Value);
return true;
}

const Pointer &ElemPtr = Ptr.atIndex(Idx);
if (!CheckInit(S, OpPC, ElemPtr))
if (!CheckLive(S, OpPC, Ptr, AK_Assign))
return false;
ElemPtr.initialize();
new (&ElemPtr.deref<T>()) T(Value);
if (Idx >= Desc->getNumElems()) {
// CheckRange.
if (S.getLangOpts().CPlusPlus) {
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_access_past_end)
<< AK_Assign << S.Current->getRange(OpPC);
}
return false;
}
Ptr.initializeElement(Idx);
new (&Ptr.elem<T>(Idx)) T(Value);
return true;
}

Expand All @@ -2148,22 +2157,32 @@ template <PrimType Name, class T = typename PrimConv<Name>::T>
bool InitElemPop(InterpState &S, CodePtr OpPC, uint32_t Idx) {
const T &Value = S.Stk.pop<T>();
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (Ptr.isUnknownSizeArray())
return false;

const Descriptor *Desc = Ptr.getFieldDesc();
// In the unlikely event that we're initializing the first item of
// a non-array, skip the atIndex().
if (Idx == 0 && !Ptr.getFieldDesc()->isArray()) {
if (Idx == 0 && !Desc->isArray()) {
Ptr.initialize();
new (&Ptr.deref<T>()) T(Value);
return true;
}

const Pointer &ElemPtr = Ptr.atIndex(Idx);
if (!CheckInit(S, OpPC, ElemPtr))
if (!CheckLive(S, OpPC, Ptr, AK_Assign))
return false;
ElemPtr.initialize();
new (&ElemPtr.deref<T>()) T(Value);
if (Idx >= Desc->getNumElems()) {
// CheckRange.
if (S.getLangOpts().CPlusPlus) {
const SourceInfo &Loc = S.Current->getSource(OpPC);
S.FFDiag(Loc, diag::note_constexpr_access_past_end)
<< AK_Assign << S.Current->getRange(OpPC);
}
return false;
}
Ptr.initializeElement(Idx);
new (&Ptr.elem<T>(Idx)) T(Value);
return true;
}

Expand Down
60 changes: 34 additions & 26 deletions clang/lib/AST/ByteCode/Pointer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,8 @@ bool Pointer::isInitialized() const {
if (!isBlockPointer())
return true;

if (isRoot() && BS.Base == sizeof(GlobalInlineDescriptor)) {
if (isRoot() && BS.Base == sizeof(GlobalInlineDescriptor) &&
Offset == BS.Base) {
const GlobalInlineDescriptor &GD =
*reinterpret_cast<const GlobalInlineDescriptor *>(block()->rawData());
return GD.InitState == GlobalInitState::Initialized;
Expand Down Expand Up @@ -461,7 +462,8 @@ bool Pointer::isElementInitialized(unsigned Index) const {
if (isStatic() && BS.Base == 0)
return true;

if (isRoot() && BS.Base == sizeof(GlobalInlineDescriptor)) {
if (isRoot() && BS.Base == sizeof(GlobalInlineDescriptor) &&
Offset == BS.Base) {
const GlobalInlineDescriptor &GD =
*reinterpret_cast<const GlobalInlineDescriptor *>(block()->rawData());
return GD.InitState == GlobalInitState::Initialized;
Expand All @@ -486,7 +488,8 @@ void Pointer::initialize() const {

assert(BS.Pointee && "Cannot initialize null pointer");

if (isRoot() && BS.Base == sizeof(GlobalInlineDescriptor)) {
if (isRoot() && BS.Base == sizeof(GlobalInlineDescriptor) &&
Offset == BS.Base) {
GlobalInlineDescriptor &GD = *reinterpret_cast<GlobalInlineDescriptor *>(
asBlockPointer().Pointee->rawData());
GD.InitState = GlobalInitState::Initialized;
Expand All @@ -496,35 +499,39 @@ void Pointer::initialize() const {
const Descriptor *Desc = getFieldDesc();
assert(Desc);
if (Desc->isPrimitiveArray()) {
// Primitive global arrays don't have an initmap.
if (isStatic() && BS.Base == 0)
return;
if (Desc->getNumElems() != 0)
initializeElement(getIndex());
return;
}

// Nothing to do for these.
if (Desc->getNumElems() == 0)
return;
// Field has its bit in an inline descriptor.
assert(BS.Base != 0 && "Only composite fields can be initialised");
getInlineDesc()->IsInitialized = true;
}

InitMapPtr &IM = getInitMap();
if (!IM)
IM =
std::make_pair(false, std::make_shared<InitMap>(Desc->getNumElems()));
void Pointer::initializeElement(unsigned Index) const {
// Primitive global arrays don't have an initmap.
if (isStatic() && BS.Base == 0)
return;

assert(IM);
assert(Index < getFieldDesc()->getNumElems());

// All initialized.
if (IM->first)
return;
InitMapPtr &IM = getInitMap();
if (!IM) {
const Descriptor *Desc = getFieldDesc();
IM = std::make_pair(false, std::make_shared<InitMap>(Desc->getNumElems()));
}

if (IM->second->initializeElement(getIndex())) {
IM->first = true;
IM->second.reset();
}
assert(IM);

// All initialized.
if (IM->first)
return;
}

// Field has its bit in an inline descriptor.
assert(BS.Base != 0 && "Only composite fields can be initialised");
getInlineDesc()->IsInitialized = true;
if (IM->second->initializeElement(Index)) {
IM->first = true;
IM->second.reset();
}
}

void Pointer::initializeAllElements() const {
Expand All @@ -547,7 +554,8 @@ bool Pointer::allElementsInitialized() const {
if (isStatic() && BS.Base == 0)
return true;

if (isRoot() && BS.Base == sizeof(GlobalInlineDescriptor)) {
if (isRoot() && BS.Base == sizeof(GlobalInlineDescriptor) &&
Offset == BS.Base) {
const GlobalInlineDescriptor &GD =
*reinterpret_cast<const GlobalInlineDescriptor *>(block()->rawData());
return GD.InitState == GlobalInitState::Initialized;
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/AST/ByteCode/Pointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,8 @@ class Pointer {

/// Initializes a field.
void initialize() const;
/// Initialized the given element of a primitive array.
void initializeElement(unsigned Index) const;
/// Initialize all elements of a primitive array at once. This can be
/// used in situations where we *know* we have initialized *all* elements
/// of a primtive array.
Expand Down