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,
31 bool IsCompleteClass =
true);
54 for (
size_t I = 0; I != NumElems; ++I) {
60 for (
size_t I = 0; I != NumElems; ++I) {
71 bool IsCompleteClass) {
75 for (
const Record::Field &F : R->fields()) {
79 if (R->isUnion() && !FieldPtr.
isActive())
82 QualType FieldType = F.Decl->getType();
89 }
else if (F.Decl->isUnnamedBitField()) {
91 }
else if (FieldDesc->
isArray()) {
99 auto diagnoseBase = [&](
const Record::Base &B,
unsigned Index) ->
bool {
101 if (
const auto *CD = dyn_cast_if_present<CXXRecordDecl>(R->getDecl())) {
102 const auto &BS = *std::next(CD->bases_begin(), Index);
104 S.
FFDiag(TypeBeginLoc, diag::note_constexpr_uninitialized_base)
105 << B.Desc->getType() <<
SourceRange(TypeBeginLoc, BS.getEndLoc());
108 << B.Desc->getType();
114 for (
auto [I, B] : llvm::enumerate(R->bases())) {
117 return diagnoseBase(B, I);
122 if (IsCompleteClass) {
123 for (
auto [I, B] : llvm::enumerate(R->virtual_bases())) {
126 return diagnoseBase(B, I);
151 if (
const auto *D = dyn_cast<const Decl *>(Source))
152 InitLoc =
cast<VarDecl>(D)->getAnyInitializer()->getExprLoc();
153 else if (
const auto *E = dyn_cast<const Expr *>(Source))
154 InitLoc = E->getExprLoc();
175 bool IsCompleteClass =
true) {
176 auto isUsefulPtr = [](
const Pointer &P) ->
bool {
177 return P.isLive() && P.isBlockPointer() && !P.isZero() && !P.isDummy() &&
178 P.isDereferencable() && !P.isUnknownSizeArray() && !P.isOnePastEnd();
192 if (!R->hasPtrField())
195 for (
const Record::Base &B : R->bases()) {
196 if (!B.R->hasPtrField())
202 for (
const Record::Field &F : R->fields()) {
209 if (IsCompleteClass) {
210 for (
const Record::Base &B : R->virtual_bases()) {
211 if (!B.R->hasPtrField())
223 if (isUsefulPtr(Pointee) && !Blocks.contains(Pointee.
block()))
230 for (
unsigned I = 0; I != Desc->
getNumElems(); ++I) {
232 if (isUsefulPtr(ElemPointee) && !Blocks.contains(ElemPointee.
block()))
239 for (
unsigned I = 0; I != Desc->
getNumElems(); ++I) {
254 llvm::SetVector<const Block *> Blocks;
258 for (
const Block *B : Blocks) {
259 if (B->isDynamic()) {
260 assert(B->getDescriptor());
261 assert(B->getDescriptor()->asExpr());
264 S.
FFDiag(Info, diag::note_constexpr_dynamic_alloc)
266 S.
Note(B->getDescriptor()->asExpr()->getExprLoc(),
267 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 checkFullyInitialized(InterpState &S, const Pointer &Ptr) const
Check that all subobjects of the given pointer have been initialized.
bool checkDynamicAllocations(InterpState &S, const Context &Ctx, const Pointer &Ptr, SourceInfo Info)
Check that none of the blocks the given pointer (transitively) points to are dynamically allocated.
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 void collectBlocks(PtrView Ptr, llvm::SetVector< const Block * > &Blocks, bool IsCompleteClass=true)
static bool CheckArrayInitialized(InterpState &S, SourceLocation Loc, PtrView BasePtr)
static bool isOrHasPtr(const Descriptor *D)
static bool CheckFieldsInitialized(InterpState &S, SourceLocation Loc, PtrView BasePtr, const Record *R, bool IsCompleteClass=true)
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.
bool isUnknownSizeArray() const
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
bool isOnePastEnd() const