1*7a6dacacSDimitry Andric //===----- EvaluationResult.cpp - Result class for the VM ------*- C++ -*-===// 2*7a6dacacSDimitry Andric // 3*7a6dacacSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*7a6dacacSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*7a6dacacSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*7a6dacacSDimitry Andric // 7*7a6dacacSDimitry Andric //===----------------------------------------------------------------------===// 8*7a6dacacSDimitry Andric 9*7a6dacacSDimitry Andric #include "EvaluationResult.h" 10*7a6dacacSDimitry Andric #include "Context.h" 11*7a6dacacSDimitry Andric #include "InterpState.h" 12*7a6dacacSDimitry Andric #include "Record.h" 13*7a6dacacSDimitry Andric #include "clang/AST/ExprCXX.h" 14*7a6dacacSDimitry Andric 15*7a6dacacSDimitry Andric namespace clang { 16*7a6dacacSDimitry Andric namespace interp { 17*7a6dacacSDimitry Andric 18*7a6dacacSDimitry Andric APValue EvaluationResult::toAPValue() const { 19*7a6dacacSDimitry Andric assert(!empty()); 20*7a6dacacSDimitry Andric switch (Kind) { 21*7a6dacacSDimitry Andric case LValue: 22*7a6dacacSDimitry Andric // Either a pointer or a function pointer. 23*7a6dacacSDimitry Andric if (const auto *P = std::get_if<Pointer>(&Value)) 24*7a6dacacSDimitry Andric return P->toAPValue(); 25*7a6dacacSDimitry Andric else if (const auto *FP = std::get_if<FunctionPointer>(&Value)) 26*7a6dacacSDimitry Andric return FP->toAPValue(); 27*7a6dacacSDimitry Andric else 28*7a6dacacSDimitry Andric llvm_unreachable("Unhandled LValue type"); 29*7a6dacacSDimitry Andric break; 30*7a6dacacSDimitry Andric case RValue: 31*7a6dacacSDimitry Andric return std::get<APValue>(Value); 32*7a6dacacSDimitry Andric case Valid: 33*7a6dacacSDimitry Andric return APValue(); 34*7a6dacacSDimitry Andric default: 35*7a6dacacSDimitry Andric llvm_unreachable("Unhandled result kind?"); 36*7a6dacacSDimitry Andric } 37*7a6dacacSDimitry Andric } 38*7a6dacacSDimitry Andric 39*7a6dacacSDimitry Andric std::optional<APValue> EvaluationResult::toRValue() const { 40*7a6dacacSDimitry Andric if (Kind == RValue) 41*7a6dacacSDimitry Andric return toAPValue(); 42*7a6dacacSDimitry Andric 43*7a6dacacSDimitry Andric assert(Kind == LValue); 44*7a6dacacSDimitry Andric 45*7a6dacacSDimitry Andric // We have a pointer and want an RValue. 46*7a6dacacSDimitry Andric if (const auto *P = std::get_if<Pointer>(&Value)) 47*7a6dacacSDimitry Andric return P->toRValue(*Ctx); 48*7a6dacacSDimitry Andric else if (const auto *FP = std::get_if<FunctionPointer>(&Value)) // Nope 49*7a6dacacSDimitry Andric return FP->toAPValue(); 50*7a6dacacSDimitry Andric llvm_unreachable("Unhandled lvalue kind"); 51*7a6dacacSDimitry Andric } 52*7a6dacacSDimitry Andric 53*7a6dacacSDimitry Andric static void DiagnoseUninitializedSubobject(InterpState &S, SourceLocation Loc, 54*7a6dacacSDimitry Andric const FieldDecl *SubObjDecl) { 55*7a6dacacSDimitry Andric assert(SubObjDecl && "Subobject declaration does not exist"); 56*7a6dacacSDimitry Andric S.FFDiag(Loc, diag::note_constexpr_uninitialized) 57*7a6dacacSDimitry Andric << /*(name)*/ 1 << SubObjDecl; 58*7a6dacacSDimitry Andric S.Note(SubObjDecl->getLocation(), 59*7a6dacacSDimitry Andric diag::note_constexpr_subobject_declared_here); 60*7a6dacacSDimitry Andric } 61*7a6dacacSDimitry Andric 62*7a6dacacSDimitry Andric static bool CheckFieldsInitialized(InterpState &S, SourceLocation Loc, 63*7a6dacacSDimitry Andric const Pointer &BasePtr, const Record *R); 64*7a6dacacSDimitry Andric 65*7a6dacacSDimitry Andric static bool CheckArrayInitialized(InterpState &S, SourceLocation Loc, 66*7a6dacacSDimitry Andric const Pointer &BasePtr, 67*7a6dacacSDimitry Andric const ConstantArrayType *CAT) { 68*7a6dacacSDimitry Andric bool Result = true; 69*7a6dacacSDimitry Andric size_t NumElems = CAT->getSize().getZExtValue(); 70*7a6dacacSDimitry Andric QualType ElemType = CAT->getElementType(); 71*7a6dacacSDimitry Andric 72*7a6dacacSDimitry Andric if (ElemType->isRecordType()) { 73*7a6dacacSDimitry Andric const Record *R = BasePtr.getElemRecord(); 74*7a6dacacSDimitry Andric for (size_t I = 0; I != NumElems; ++I) { 75*7a6dacacSDimitry Andric Pointer ElemPtr = BasePtr.atIndex(I).narrow(); 76*7a6dacacSDimitry Andric Result &= CheckFieldsInitialized(S, Loc, ElemPtr, R); 77*7a6dacacSDimitry Andric } 78*7a6dacacSDimitry Andric } else if (const auto *ElemCAT = dyn_cast<ConstantArrayType>(ElemType)) { 79*7a6dacacSDimitry Andric for (size_t I = 0; I != NumElems; ++I) { 80*7a6dacacSDimitry Andric Pointer ElemPtr = BasePtr.atIndex(I).narrow(); 81*7a6dacacSDimitry Andric Result &= CheckArrayInitialized(S, Loc, ElemPtr, ElemCAT); 82*7a6dacacSDimitry Andric } 83*7a6dacacSDimitry Andric } else { 84*7a6dacacSDimitry Andric for (size_t I = 0; I != NumElems; ++I) { 85*7a6dacacSDimitry Andric if (!BasePtr.atIndex(I).isInitialized()) { 86*7a6dacacSDimitry Andric DiagnoseUninitializedSubobject(S, Loc, BasePtr.getField()); 87*7a6dacacSDimitry Andric Result = false; 88*7a6dacacSDimitry Andric } 89*7a6dacacSDimitry Andric } 90*7a6dacacSDimitry Andric } 91*7a6dacacSDimitry Andric 92*7a6dacacSDimitry Andric return Result; 93*7a6dacacSDimitry Andric } 94*7a6dacacSDimitry Andric 95*7a6dacacSDimitry Andric static bool CheckFieldsInitialized(InterpState &S, SourceLocation Loc, 96*7a6dacacSDimitry Andric const Pointer &BasePtr, const Record *R) { 97*7a6dacacSDimitry Andric assert(R); 98*7a6dacacSDimitry Andric bool Result = true; 99*7a6dacacSDimitry Andric // Check all fields of this record are initialized. 100*7a6dacacSDimitry Andric for (const Record::Field &F : R->fields()) { 101*7a6dacacSDimitry Andric Pointer FieldPtr = BasePtr.atField(F.Offset); 102*7a6dacacSDimitry Andric QualType FieldType = F.Decl->getType(); 103*7a6dacacSDimitry Andric 104*7a6dacacSDimitry Andric if (FieldType->isRecordType()) { 105*7a6dacacSDimitry Andric Result &= CheckFieldsInitialized(S, Loc, FieldPtr, FieldPtr.getRecord()); 106*7a6dacacSDimitry Andric } else if (FieldType->isIncompleteArrayType()) { 107*7a6dacacSDimitry Andric // Nothing to do here. 108*7a6dacacSDimitry Andric } else if (FieldType->isArrayType()) { 109*7a6dacacSDimitry Andric const auto *CAT = 110*7a6dacacSDimitry Andric cast<ConstantArrayType>(FieldType->getAsArrayTypeUnsafe()); 111*7a6dacacSDimitry Andric Result &= CheckArrayInitialized(S, Loc, FieldPtr, CAT); 112*7a6dacacSDimitry Andric } else if (!FieldPtr.isInitialized()) { 113*7a6dacacSDimitry Andric DiagnoseUninitializedSubobject(S, Loc, F.Decl); 114*7a6dacacSDimitry Andric Result = false; 115*7a6dacacSDimitry Andric } 116*7a6dacacSDimitry Andric } 117*7a6dacacSDimitry Andric 118*7a6dacacSDimitry Andric // Check Fields in all bases 119*7a6dacacSDimitry Andric for (const Record::Base &B : R->bases()) { 120*7a6dacacSDimitry Andric Pointer P = BasePtr.atField(B.Offset); 121*7a6dacacSDimitry Andric if (!P.isInitialized()) { 122*7a6dacacSDimitry Andric S.FFDiag(BasePtr.getDeclDesc()->asDecl()->getLocation(), 123*7a6dacacSDimitry Andric diag::note_constexpr_uninitialized_base) 124*7a6dacacSDimitry Andric << B.Desc->getType(); 125*7a6dacacSDimitry Andric return false; 126*7a6dacacSDimitry Andric } 127*7a6dacacSDimitry Andric Result &= CheckFieldsInitialized(S, Loc, P, B.R); 128*7a6dacacSDimitry Andric } 129*7a6dacacSDimitry Andric 130*7a6dacacSDimitry Andric // TODO: Virtual bases 131*7a6dacacSDimitry Andric 132*7a6dacacSDimitry Andric return Result; 133*7a6dacacSDimitry Andric } 134*7a6dacacSDimitry Andric 135*7a6dacacSDimitry Andric bool EvaluationResult::checkFullyInitialized(InterpState &S) const { 136*7a6dacacSDimitry Andric assert(Source); 137*7a6dacacSDimitry Andric assert(isLValue()); 138*7a6dacacSDimitry Andric 139*7a6dacacSDimitry Andric // Our Source must be a VarDecl. 140*7a6dacacSDimitry Andric const Decl *SourceDecl = Source.dyn_cast<const Decl *>(); 141*7a6dacacSDimitry Andric assert(SourceDecl); 142*7a6dacacSDimitry Andric const auto *VD = cast<VarDecl>(SourceDecl); 143*7a6dacacSDimitry Andric assert(VD->getType()->isRecordType() || VD->getType()->isArrayType()); 144*7a6dacacSDimitry Andric SourceLocation InitLoc = VD->getAnyInitializer()->getExprLoc(); 145*7a6dacacSDimitry Andric 146*7a6dacacSDimitry Andric const Pointer &Ptr = *std::get_if<Pointer>(&Value); 147*7a6dacacSDimitry Andric assert(!Ptr.isZero()); 148*7a6dacacSDimitry Andric 149*7a6dacacSDimitry Andric if (const Record *R = Ptr.getRecord()) 150*7a6dacacSDimitry Andric return CheckFieldsInitialized(S, InitLoc, Ptr, R); 151*7a6dacacSDimitry Andric const auto *CAT = 152*7a6dacacSDimitry Andric cast<ConstantArrayType>(Ptr.getType()->getAsArrayTypeUnsafe()); 153*7a6dacacSDimitry Andric return CheckArrayInitialized(S, InitLoc, Ptr, CAT); 154*7a6dacacSDimitry Andric 155*7a6dacacSDimitry Andric return true; 156*7a6dacacSDimitry Andric } 157*7a6dacacSDimitry Andric 158*7a6dacacSDimitry Andric void EvaluationResult::dump() const { 159*7a6dacacSDimitry Andric assert(Ctx); 160*7a6dacacSDimitry Andric auto &OS = llvm::errs(); 161*7a6dacacSDimitry Andric const ASTContext &ASTCtx = Ctx->getASTContext(); 162*7a6dacacSDimitry Andric 163*7a6dacacSDimitry Andric switch (Kind) { 164*7a6dacacSDimitry Andric case Empty: 165*7a6dacacSDimitry Andric OS << "Empty\n"; 166*7a6dacacSDimitry Andric break; 167*7a6dacacSDimitry Andric case RValue: 168*7a6dacacSDimitry Andric OS << "RValue: "; 169*7a6dacacSDimitry Andric std::get<APValue>(Value).dump(OS, ASTCtx); 170*7a6dacacSDimitry Andric break; 171*7a6dacacSDimitry Andric case LValue: { 172*7a6dacacSDimitry Andric assert(Source); 173*7a6dacacSDimitry Andric QualType SourceType; 174*7a6dacacSDimitry Andric if (const auto *D = Source.dyn_cast<const Decl *>()) { 175*7a6dacacSDimitry Andric if (const auto *VD = dyn_cast<ValueDecl>(D)) 176*7a6dacacSDimitry Andric SourceType = VD->getType(); 177*7a6dacacSDimitry Andric } else if (const auto *E = Source.dyn_cast<const Expr *>()) { 178*7a6dacacSDimitry Andric SourceType = E->getType(); 179*7a6dacacSDimitry Andric } 180*7a6dacacSDimitry Andric 181*7a6dacacSDimitry Andric OS << "LValue: "; 182*7a6dacacSDimitry Andric if (const auto *P = std::get_if<Pointer>(&Value)) 183*7a6dacacSDimitry Andric P->toAPValue().printPretty(OS, ASTCtx, SourceType); 184*7a6dacacSDimitry Andric else if (const auto *FP = std::get_if<FunctionPointer>(&Value)) // Nope 185*7a6dacacSDimitry Andric FP->toAPValue().printPretty(OS, ASTCtx, SourceType); 186*7a6dacacSDimitry Andric OS << "\n"; 187*7a6dacacSDimitry Andric break; 188*7a6dacacSDimitry Andric } 189*7a6dacacSDimitry Andric 190*7a6dacacSDimitry Andric default: 191*7a6dacacSDimitry Andric llvm_unreachable("Can't print that."); 192*7a6dacacSDimitry Andric } 193*7a6dacacSDimitry Andric } 194*7a6dacacSDimitry Andric 195*7a6dacacSDimitry Andric } // namespace interp 196*7a6dacacSDimitry Andric } // namespace clang 197