13#include "llvm/ADT/STLExtras.h"
14#include "llvm/ADT/SetVector.h"
22 assert(SubObjDecl &&
"Subobject declaration does not exist");
23 S.
FFDiag(Loc, diag::note_constexpr_uninitialized)
26 diag::note_constexpr_subobject_declared_here);
30 PtrView BasePtr,
const Record *R);
53 for (
size_t I = 0; I != NumElems; ++I) {
59 for (
size_t I = 0; I != NumElems; ++I) {
73 for (
const Record::Field &F : R->fields()) {
77 if (R->isUnion() && !FieldPtr.
isActive())
80 QualType FieldType = F.Decl->getType();
87 }
else if (F.Decl->isUnnamedBitField()) {
89 }
else if (FieldDesc->
isArray()) {
98 for (
auto [I, B] : llvm::enumerate(R->bases())) {
102 if (
const auto *CD = dyn_cast_if_present<CXXRecordDecl>(R->getDecl())) {
103 const auto &BS = *std::next(CD->bases_begin(), I);
105 S.
FFDiag(TypeBeginLoc, diag::note_constexpr_uninitialized_base)
106 << B.Desc->getType() <<
SourceRange(TypeBeginLoc, BS.getEndLoc());
109 << B.Desc->getType();
136 if (
const auto *D = dyn_cast<const Decl *>(Source))
137 InitLoc =
cast<VarDecl>(D)->getAnyInitializer()->getExprLoc();
138 else if (
const auto *E = dyn_cast<const Expr *>(Source))
139 InitLoc = E->getExprLoc();
160 auto isUsefulPtr = [](
const Pointer &P) ->
bool {
161 return P.isLive() && P.isBlockPointer() && !P.isZero() && !P.isDummy() &&
162 P.isDereferencable() && !P.isUnknownSizeArray() && !P.isOnePastEnd();
165 if (!isUsefulPtr(
Pointer(Ptr)))
176 for (
const Record::Field &F : R->fields()) {
184 if (isUsefulPtr(Pointee) && !Blocks.contains(Pointee.
block()))
188 for (
unsigned I = 0; I != Desc->
getNumElems(); ++I) {
190 if (isUsefulPtr(ElemPointee) && !Blocks.contains(ElemPointee.
block()))
194 for (
unsigned I = 0; I != Desc->
getNumElems(); ++I) {
208 llvm::SetVector<const Block *> Blocks;
212 for (
const Block *B : Blocks) {
213 if (B->isDynamic()) {
214 assert(B->getDescriptor());
215 assert(B->getDescriptor()->asExpr());
218 S.
FFDiag(Info, diag::note_constexpr_dynamic_alloc)
220 S.
Note(B->getDescriptor()->asExpr()->getExprLoc(),
221 diag::note_constexpr_dynamic_alloc_here);
llvm::MachO::Record Record
SourceLocation getLocation() const
Represents a member of a struct/union/class.
A (possibly-)qualified type.
Encodes a location in the source.
A trivial tuple used to represent a source range.
bool isIncompleteArrayType() const
bool isReferenceType() const
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
A memory block, either on the stack or in the heap.
Holds all information required to evaluate constexpr code in a module.
bool checkReturnValue(InterpState &S, const Context &Ctx, const Pointer &Ptr, const SourceInfo &Info)
Check that none of the blocks the given pointer (transitively) points to are dynamically allocated.
bool checkFullyInitialized(InterpState &S, const Pointer &Ptr) const
Check that all subobjects of the given pointer have been initialized.
A pointer to a memory block, live or dead.
QualType getType() const
Returns the type of the innermost field.
bool isArrayElement() const
Checks if the pointer points to an array.
bool isLive() const
Checks if the pointer is live.
bool isZero() const
Checks if the pointer is null.
bool isRoot() const
Pointer points directly to a block.
bool isBlockPointer() const
const Block * block() const
const Record * getRecord() const
Returns the record descriptor of a class.
Structure/Class descriptor.
bool hasPtrField() const
If this record (or any of its bases) contains a field of type PT_Ptr.
Describes the statement/declaration an opcode was generated from.
OptionalDiagnostic Note(SourceLocation Loc, diag::kind DiagId)
Add a note to a prior diagnostic.
OptionalDiagnostic FFDiag(SourceLocation Loc, diag::kind DiagId=diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes=0)
Diagnose that the evaluation could not be folded (FF => FoldFailure)
static bool CheckFieldsInitialized(InterpState &S, SourceLocation Loc, PtrView BasePtr, const Record *R)
static void collectBlocks(PtrView Ptr, llvm::SetVector< const Block * > &Blocks)
static bool CheckArrayInitialized(InterpState &S, SourceLocation Loc, PtrView BasePtr)
static bool isOrHasPtr(const Descriptor *D)
static void DiagnoseUninitializedSubobject(InterpState &S, SourceLocation Loc, const FieldDecl *SubObjDecl)
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.
U cast(CodeGen::Address addr)
Describes a memory block created by an allocation site.
unsigned getNumElems() const
Returns the number of elements stored in the block.
bool isPrimitive() const
Checks if the descriptor is of a primitive.
bool isCompositeArray() const
Checks if the descriptor is of an array of composites.
const Descriptor *const ElemDesc
Descriptor of the array element.
SourceLocation getLocation() const
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
PrimType getPrimType() const
bool isRecord() const
Checks if the descriptor is of a record.
const Record *const ElemRecord
Pointer to the record, if block contains records.
bool isArray() const
Checks if the descriptor is of an array.
const Descriptor * getDeclDesc() const
bool allElementsInitialized() const
PtrView atField(unsigned Offset) const
const Record * getRecord() const
const Descriptor * getFieldDesc() const
const FieldDecl * getField() const
PtrView atIndex(unsigned Idx) const
T & elem(unsigned I) const
bool isInitialized() const