Skip to content

Commit 92e2fd6

Browse files
committed
Fix build failure 'sizeof(clang::APValue::LV) <= DataSize': LV too big'
Ensure APValue::DataSize is bigger than APValue::LV. To do so, this moves APValue::LV to APValue.h so that we can always allocate DataSize to be bigger than LV. Previously, LV was hidden in the source file and the type size of DataSize didn't take it into account even though it has to be bigger than LV. This made the implementation quite fragile to any change in the size of related components. rdar://137823177
1 parent 579c85a commit 92e2fd6

File tree

2 files changed

+34
-30
lines changed

2 files changed

+34
-30
lines changed

clang/include/clang/AST/APValue.h

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#ifndef LLVM_CLANG_AST_APVALUE_H
1414
#define LLVM_CLANG_AST_APVALUE_H
1515

16+
#include "clang/AST/CharUnits.h"
1617
#include "clang/Basic/LLVM.h"
1718
#include "llvm/ADT/APFixedPoint.h"
1819
#include "llvm/ADT/APFloat.h"
@@ -29,7 +30,6 @@ template <typename T> class BasicReaderBase;
2930

3031
class AddrLabelExpr;
3132
class ASTContext;
32-
class CharUnits;
3333
class CXXRecordDecl;
3434
class Decl;
3535
class DiagnosticBuilder;
@@ -419,10 +419,41 @@ class APValue {
419419
};
420420
struct MemberPointerData;
421421

422+
struct LVBase {
423+
APValue::LValueBase Base;
424+
CharUnits Offset;
425+
// BoundsSafety : While the base also holds a corresponding constant array type
426+
// for forged pointer, we still keep track of forged size because the array
427+
// size will be different from the actual forged size if it is not a multiple
428+
// of element type size after a bitcast. The codegen doesn't round up/down
429+
// the bounds to be a type-size multiple, we should keep it the same for
430+
// constant emission. Once __builtin_forge_* has a type as an argument, we
431+
// may consider round down the size with the element type size.
432+
CharUnits ForgedSize;
433+
// While 'Offset' is the offset within the LValue, 'ForgedOffset' is the
434+
// offset of the base pointer of __builtin_unsafe_forge*. For example, in
435+
// the following,
436+
// '__bidi_indexable_unsafe_forge_bidi_indexable(base + N) + M'
437+
// 'N' should be 'ForgedOffset' and 'M' should be 'Offset'. This way, the
438+
// forged pointer itself becomes an LValue starting at base + 'ForgedOffset'.
439+
CharUnits ForgedOffset;
440+
unsigned PathLength;
441+
bool IsNullPtr : 1;
442+
bool IsOnePastTheEnd : 1;
443+
bool IsForgeBidi : 1;
444+
bool IsForgeSingle : 1;
445+
bool IsForgeTerminatedBy : 1;
446+
};
447+
448+
struct LVPlaceHolder {
449+
LVBase Base;
450+
LValuePathEntry Path[1];
451+
};
452+
422453
// We ensure elsewhere that Data is big enough for LV and MemberPointerData.
423454
typedef llvm::AlignedCharArrayUnion<void *, APSInt, APFloat, ComplexAPSInt,
424455
ComplexAPFloat, Vec, Arr, StructData,
425-
UnionData, AddrLabelDiffData> DataType;
456+
UnionData, AddrLabelDiffData, LVPlaceHolder> DataType;
426457
static const size_t DataSize = sizeof(DataType);
427458

428459
DataType Data;

clang/lib/AST/APValue.cpp

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -195,34 +195,6 @@ QualType APValue::LValuePathSerializationHelper::getType() {
195195
return QualType::getFromOpaquePtr(Ty);
196196
}
197197

198-
namespace {
199-
struct LVBase {
200-
APValue::LValueBase Base;
201-
CharUnits Offset;
202-
// BoundsSafety : While the base also holds a corresponding constant array type
203-
// for forged pointer, we still keep track of forged size because the array
204-
// size will be different from the actual forged size if it is not a multiple
205-
// of element type size after a bitcast. The codegen doesn't round up/down
206-
// the bounds to be a type-size multiple, we should keep it the same for
207-
// constant emission. Once __builtin_forge_* has a type as an argument, we
208-
// may consider round down the size with the element type size.
209-
CharUnits ForgedSize;
210-
// While 'Offset' is the offset within the LValue, 'ForgedOffset' is the
211-
// offset of the base pointer of __builtin_unsafe_forge*. For example, in
212-
// the following,
213-
// '__bidi_indexable_unsafe_forge_bidi_indexable(base + N) + M'
214-
// 'N' should be 'ForgedOffset' and 'M' should be 'Offset'. This way, the
215-
// forged pointer itself becomes an LValue starting at base + 'ForgedOffset'.
216-
CharUnits ForgedOffset;
217-
unsigned PathLength;
218-
bool IsNullPtr : 1;
219-
bool IsOnePastTheEnd : 1;
220-
bool IsForgeBidi : 1;
221-
bool IsForgeSingle : 1;
222-
bool IsForgeTerminatedBy : 1;
223-
};
224-
}
225-
226198
void *APValue::LValueBase::getOpaqueValue() const {
227199
return Ptr.getOpaqueValue();
228200
}
@@ -274,6 +246,7 @@ bool llvm::DenseMapInfo<clang::APValue::LValueBase>::isEqual(
274246
}
275247

276248
struct APValue::LV : LVBase {
249+
static_assert(DataSize >= sizeof(LVBase) && "LVBase too big");
277250
static const unsigned InlinePathSpace =
278251
(DataSize - sizeof(LVBase)) / sizeof(LValuePathEntry);
279252

0 commit comments

Comments
 (0)