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);
45 for (
size_t I = 0; I != NumElems; ++I) {
49 }
else if (
const auto *ElemCAT = dyn_cast<ConstantArrayType>(ElemType)) {
50 for (
size_t I = 0; I != NumElems; ++I) {
65 for (
size_t I = 0; I != NumElems; ++I) {
81 for (
const Record::Field &F : R->
fields()) {
83 QualType FieldType = F.Decl->getType();
93 }
else if (F.Decl->isUnnamedBitField()) {
106 for (
auto [I, B] : llvm::enumerate(R->
bases())) {
110 if (
const auto *CD = dyn_cast_if_present<CXXRecordDecl>(R->
getDecl())) {
111 const auto &BS = *std::next(CD->bases_begin(), I);
113 S.
FFDiag(TypeBeginLoc, diag::note_constexpr_uninitialized_base)
114 << B.Desc->getType() <<
SourceRange(TypeBeginLoc, BS.getEndLoc());
117 << B.Desc->getType();
143 if (
const auto *D = dyn_cast<const Decl *>(Source))
144 InitLoc =
cast<VarDecl>(D)->getAnyInitializer()->getExprLoc();
145 else if (
const auto *E = dyn_cast<const Expr *>(Source))
146 InitLoc = E->getExprLoc();
151 if (
const auto *CAT = dyn_cast_if_present<ConstantArrayType>(
159 llvm::SetVector<const Block *> &Blocks) {
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(Ptr))
168 Blocks.insert(Ptr.
block());
175 for (
const Record::Field &F : R->fields()) {
182 if (isUsefulPtr(Pointee) && !Blocks.contains(Pointee.
block()))
186 for (
unsigned I = 0; I != Desc->
getNumElems(); ++I) {
188 if (isUsefulPtr(ElemPointee) && !Blocks.contains(ElemPointee.
block()))
192 for (
unsigned I = 0; I != Desc->
getNumElems(); ++I) {
204 llvm::SetVector<const Block *> Blocks;
208 for (
const Block *B : Blocks) {
209 if (B->isDynamic()) {
210 assert(B->getDescriptor());
211 assert(B->getDescriptor()->asExpr());
214 S.
FFDiag(Info, diag::note_constexpr_dynamic_alloc)
216 S.
Note(B->getDescriptor()->asExpr()->getExprLoc(),
217 diag::note_constexpr_dynamic_alloc_here);
llvm::MachO::Record Record
QualType getElementType() const
Represents the canonical version of C arrays with a specified constant size.
uint64_t getZExtSize() const
Return the size zero-extended as a uint64_t.
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.
bool isRecordType() const
A memory block, either on the stack or in the heap.
Holds all information required to evaluate constexpr code in a module.
bool canClassify(QualType T)
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.
Context & getContext() const
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.
bool isElementInitialized(unsigned Index) const
Like isInitialized(), but for primitive arrays.
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 Record * getElemRecord() const
Returns the element record type, if this is a non-primive array.
const FieldDecl * getField() const
Returns the field information.
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.
const RecordDecl * getDecl() const
Returns the underlying declaration.
bool isUnion() const
Checks if the record is a union.
llvm::iterator_range< const_base_iter > bases() const
llvm::iterator_range< const_field_iter > fields() const
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 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, const ConstantArrayType *CAT)
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.
SourceLocation getLocation() const
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
PrimType getPrimType() const
const Record *const ElemRecord
Pointer to the record, if block contains records.