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);
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();
137 if (
const auto *D = dyn_cast<const Decl *>(Source))
138 InitLoc =
cast<VarDecl>(D)->getAnyInitializer()->getExprLoc();
139 else if (
const auto *E = dyn_cast<const Expr *>(Source))
140 InitLoc = E->getExprLoc();
161 llvm::SetVector<const Block *> &Blocks) {
162 auto isUsefulPtr = [](
const Pointer &P) ->
bool {
163 return P.isLive() && P.isBlockPointer() && !P.isZero() && !P.isDummy() &&
164 P.isDereferencable() && !P.isUnknownSizeArray() && !P.isOnePastEnd();
167 if (!isUsefulPtr(Ptr))
170 Blocks.insert(Ptr.
block());
178 for (
const Record::Field &F : R->fields()) {
187 if (isUsefulPtr(Pointee) && !Blocks.contains(Pointee.
block()))
191 for (
unsigned I = 0; I != Desc->
getNumElems(); ++I) {
193 if (isUsefulPtr(ElemPointee) && !Blocks.contains(ElemPointee.
block()))
197 for (
unsigned I = 0; I != Desc->
getNumElems(); ++I) {
209 llvm::SetVector<const Block *> Blocks;
213 for (
const Block *B : Blocks) {
214 if (B->isDynamic()) {
215 assert(B->getDescriptor());
216 assert(B->getDescriptor()->asExpr());
219 S.
FFDiag(Info, diag::note_constexpr_dynamic_alloc)
221 S.
Note(B->getDescriptor()->asExpr()->getExprLoc(),
222 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.
Pointer narrow() const
Restricts the scope of an array element pointer.
bool isInitialized() const
Checks if an object was initialized.
Pointer atIndex(uint64_t Idx) const
Offsets a pointer inside an array.
bool isActive() const
Checks if the object is active.
Pointer atField(unsigned Off) const
Creates a pointer to a field.
T & deref() const
Dereferences the pointer, if it's live.
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.
T & elem(unsigned I) const
Dereferences the element at index I.
bool isZero() const
Checks if the pointer is null.
bool isRoot() const
Pointer points directly to a block.
const Descriptor * getDeclDesc() const
Accessor for information about the declaration site.
const FieldDecl * getField() const
Returns the field information.
bool isBlockPointer() const
bool allElementsInitialized() const
const Block * block() const
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
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 isOrHasPtr(const Descriptor *D)
static void collectBlocks(const Pointer &Ptr, llvm::SetVector< const Block * > &Blocks)
static bool CheckFieldsInitialized(InterpState &S, SourceLocation Loc, const Pointer &BasePtr, const Record *R)
static void DiagnoseUninitializedSubobject(InterpState &S, SourceLocation Loc, const FieldDecl *SubObjDecl)
static bool CheckArrayInitialized(InterpState &S, SourceLocation Loc, const Pointer &BasePtr)
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.