13#include "llvm/ADT/STLExtras.h"
14#include "llvm/ADT/SmallPtrSet.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);
142 if (!Ptr.isBlockPointer())
151 if (
const auto *D = Source.asDecl())
152 InitLoc =
cast<VarDecl>(D)->getAnyInitializer()->getExprLoc();
153 else if (
const auto *E = Source.asExpr())
154 InitLoc = E->getExprLoc();
156 if (
const Record *R = Ptr.getRecord())
159 if (isa_and_nonnull<ConstantArrayType>(Ptr.getType()->getAsArrayTypeUnsafe()))
176 bool IsCompleteClass =
true) {
177 auto isUsefulPtr = [](
const Pointer &P) ->
bool {
178 return P.isLive() && P.isBlockPointer() && !P.isZero() && !P.isDummy() &&
179 P.isDereferencable() && !P.isUnknownSizeArray() && !P.isOnePastEnd();
182 if (!Ptr.isLive() || Ptr.isZero() || Ptr.isDummy() ||
183 Ptr.isUnknownSizeArray() || Ptr.isOnePastEnd())
186 Blocks.insert(Ptr.Pointee);
193 if (!R->hasPtrField())
196 for (
const Record::Base &B : R->bases()) {
197 if (!B.R->hasPtrField())
199 PtrView BasePtr = Ptr.atField(B.Offset);
203 for (
const Record::Field &F : R->fields()) {
206 PtrView FieldPtr = Ptr.atField(F.Offset);
210 if (IsCompleteClass) {
211 for (
const Record::Base &B : R->virtual_bases()) {
212 if (!B.R->hasPtrField())
214 PtrView BasePtr = Ptr.atField(B.Offset);
224 if (isUsefulPtr(Pointee) && !Blocks.contains(Pointee.
block()))
231 for (
unsigned I = 0; I != Desc->
getNumElems(); ++I) {
233 if (isUsefulPtr(ElemPointee) && !Blocks.contains(ElemPointee.
block()))
240 for (
unsigned I = 0; I != Desc->
getNumElems(); ++I) {
241 PtrView ElemPtr = Ptr.atIndex(I).narrow();
250 if (!Ptr.isBlockPointer())
258 for (
const Block *B : Blocks) {
259 if (B->isDynamic()) {
260 assert(B->getDescriptor());
261 assert(B->getDescriptor()->asExpr());
263 bool IsSubobj = !Ptr.isRoot() || Ptr.isArrayElement();
264 S.
FFDiag(Info, diag::note_constexpr_dynamic_alloc)
265 << Ptr.getType()->isReferenceType() << IsSubobj;
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
A memory block, either on the stack or in the heap.
bool checkDynamicAllocations(InterpState &S, const Pointer &Ptr, 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.
const Block * block() const
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 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)
static void collectBlocks(PtrView Ptr, llvm::SmallPtrSet< const Block *, 4 > &Blocks, bool IsCompleteClass=true)
Top level wrappers for InstallAPI frontend operations.
@ 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
bool isInitialized() const