13#include "llvm/ADT/STLExtras.h"
14#include "llvm/ADT/SetVector.h"
25 if (
const auto *
P = std::get_if<Pointer>(&
Value))
27 else if (
const auto *FP = std::get_if<FunctionPointer>(&
Value))
30 llvm_unreachable(
"Unhandled LValue type");
33 return std::get<APValue>(
Value);
37 llvm_unreachable(
"Unhandled result kind?");
48 if (
const auto *
P = std::get_if<Pointer>(&
Value))
50 else if (
const auto *FP = std::get_if<FunctionPointer>(&
Value))
52 llvm_unreachable(
"Unhandled lvalue kind");
57 assert(SubObjDecl &&
"Subobject declaration does not exist");
58 S.FFDiag(
Loc, diag::note_constexpr_uninitialized)
61 diag::note_constexpr_subobject_declared_here);
65 const Pointer &BasePtr,
const Record *R);
76 for (
size_t I = 0; I != NumElems; ++I) {
80 }
else if (
const auto *ElemCAT = dyn_cast<ConstantArrayType>(ElemType)) {
81 for (
size_t I = 0; I != NumElems; ++I) {
86 for (
size_t I = 0; I != NumElems; ++I) {
102 for (
const Record::Field &F : R->
fields()) {
104 QualType FieldType = F.Decl->getType();
114 }
else if (F.Decl->isUnnamedBitField()) {
127 for (
auto [I, B] : llvm::enumerate(R->
bases())) {
129 if (!
P.isInitialized()) {
131 if (
const auto *CD = dyn_cast_if_present<CXXRecordDecl>(R->
getDecl())) {
132 const auto &BS = *std::next(CD->bases_begin(), I);
133 S.FFDiag(BS.getBaseTypeLoc(), diag::note_constexpr_uninitialized_base)
134 << B.Desc->getType() << BS.getSourceRange();
136 S.FFDiag(Desc->
getLocation(), diag::note_constexpr_uninitialized_base)
137 << B.Desc->getType();
163 if (
const auto *
D = Source.dyn_cast<
const Decl *>())
164 InitLoc = cast<VarDecl>(
D)->getAnyInitializer()->getExprLoc();
165 else if (
const auto *
E = Source.dyn_cast<
const Expr *>())
166 InitLoc =
E->getExprLoc();
171 if (
const auto *CAT = dyn_cast_if_present<ConstantArrayType>(
179 llvm::SetVector<const Block *> &Blocks) {
180 auto isUsefulPtr = [](
const Pointer &
P) ->
bool {
181 return P.isLive() && !
P.isZero() && !
P.isDummy() &&
182 !
P.isUnknownSizeArray() && !
P.isOnePastEnd() &&
P.isBlockPointer();
185 if (!isUsefulPtr(Ptr))
188 Blocks.insert(Ptr.
block());
195 for (
const Record::Field &F : R->fields()) {
202 if (isUsefulPtr(Pointee) && !Blocks.contains(Pointee.
block()))
206 for (
unsigned I = 0; I != Desc->
getNumElems(); ++I) {
208 if (isUsefulPtr(ElemPointee) && !Blocks.contains(ElemPointee.
block()))
212 for (
unsigned I = 0; I != Desc->
getNumElems(); ++I) {
224 llvm::SetVector<const Block *> Blocks;
228 for (
const Block *B : Blocks) {
229 if (B->isDynamic()) {
230 assert(B->getDescriptor());
231 assert(B->getDescriptor()->asExpr());
233 S.FFDiag(Info, diag::note_constexpr_dynamic_alloc)
235 S.Note(B->getDescriptor()->asExpr()->getExprLoc(),
236 diag::note_constexpr_dynamic_alloc_here);
Defines the clang::Expr interface and subclasses for C++ expressions.
llvm::MachO::Record Record
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
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.
Decl - This represents one declaration (or definition), e.g.
SourceLocation getLocation() const
This represents one expression.
Represents a member of a struct/union/class.
A (possibly-)qualified type.
Encodes a location in the source.
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.
ASTContext & getASTContext() const
Returns the AST context.
std::optional< APValue > toRValue() const
If the result is an LValue, convert that to an RValue and return it.
APValue toAPValue() const
Returns an APValue for the evaluation result.
QualType getSourceType() const
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 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.
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.
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.
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.
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.