1a07aba5dSTimm Baeder #include "../../../lib/AST/ByteCode/Descriptor.h" 2a07aba5dSTimm Baeder #include "../../../lib/AST/ByteCode/Context.h" 3a07aba5dSTimm Baeder #include "../../../lib/AST/ByteCode/Program.h" 4a07aba5dSTimm Baeder #include "clang/AST/ASTContext.h" 5a07aba5dSTimm Baeder #include "clang/AST/Decl.h" 6a07aba5dSTimm Baeder #include "clang/ASTMatchers/ASTMatchFinder.h" 7a07aba5dSTimm Baeder #include "clang/ASTMatchers/ASTMatchers.h" 8a07aba5dSTimm Baeder #include "clang/Tooling/Tooling.h" 9a07aba5dSTimm Baeder #include "gtest/gtest.h" 10a07aba5dSTimm Baeder 11a07aba5dSTimm Baeder using namespace clang; 12a07aba5dSTimm Baeder using namespace clang::interp; 13a07aba5dSTimm Baeder using namespace clang::ast_matchers; 14a07aba5dSTimm Baeder 15a07aba5dSTimm Baeder /// Inspect generated Descriptors as well as the pointers we create. 16a07aba5dSTimm Baeder /// 17a07aba5dSTimm Baeder TEST(Descriptor, Primitives) { 18a07aba5dSTimm Baeder constexpr char Code[] = "struct A { bool a; bool b; };\n" 19a07aba5dSTimm Baeder "struct S {\n" 20a07aba5dSTimm Baeder " float f;\n" 21a07aba5dSTimm Baeder " char s[4];\n" 22a07aba5dSTimm Baeder " A a[3];\n" 23a07aba5dSTimm Baeder " short l[3][3];\n" 24a07aba5dSTimm Baeder " int EmptyA[0];\n" 25a07aba5dSTimm Baeder "};\n" 26a07aba5dSTimm Baeder "constexpr S d = {0.0, \"foo\", {{true, false}, " 27a07aba5dSTimm Baeder "{false, true}, {false, false}},\n" 28a07aba5dSTimm Baeder " {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}, {}};\n"; 29a07aba5dSTimm Baeder 30a07aba5dSTimm Baeder auto AST = tooling::buildASTFromCodeWithArgs( 31a07aba5dSTimm Baeder Code, {"-fexperimental-new-constant-interpreter"}); 32a07aba5dSTimm Baeder 33a07aba5dSTimm Baeder const VarDecl *D = selectFirst<VarDecl>( 34a07aba5dSTimm Baeder "d", match(varDecl().bind("d"), AST->getASTContext())); 35a07aba5dSTimm Baeder ASSERT_NE(D, nullptr); 36a07aba5dSTimm Baeder 37a07aba5dSTimm Baeder const auto &Ctx = AST->getASTContext().getInterpContext(); 38a07aba5dSTimm Baeder Program &Prog = Ctx.getProgram(); 39a07aba5dSTimm Baeder // Global is registered. 40a07aba5dSTimm Baeder ASSERT_TRUE(Prog.getGlobal(D)); 41a07aba5dSTimm Baeder 42a07aba5dSTimm Baeder // Get a Pointer to the global. 43a07aba5dSTimm Baeder const Pointer &GlobalPtr = Prog.getPtrGlobal(*Prog.getGlobal(D)); 44a07aba5dSTimm Baeder 45a07aba5dSTimm Baeder // Test Descriptor of the struct S. 46a07aba5dSTimm Baeder const Descriptor *GlobalDesc = GlobalPtr.getFieldDesc(); 47a07aba5dSTimm Baeder ASSERT_TRUE(GlobalDesc == GlobalPtr.getDeclDesc()); 48a07aba5dSTimm Baeder 49a07aba5dSTimm Baeder ASSERT_TRUE(GlobalDesc->asDecl() == D); 50a07aba5dSTimm Baeder ASSERT_FALSE(GlobalDesc->asExpr()); 51a07aba5dSTimm Baeder ASSERT_TRUE(GlobalDesc->asValueDecl() == D); 52a07aba5dSTimm Baeder ASSERT_FALSE(GlobalDesc->asFieldDecl()); 53a07aba5dSTimm Baeder ASSERT_FALSE(GlobalDesc->asRecordDecl()); 54a07aba5dSTimm Baeder 55a07aba5dSTimm Baeder // Still true because this is a global variable. 56a07aba5dSTimm Baeder ASSERT_TRUE(GlobalDesc->getMetadataSize() == sizeof(GlobalInlineDescriptor)); 57a07aba5dSTimm Baeder ASSERT_FALSE(GlobalDesc->isPrimitiveArray()); 58a07aba5dSTimm Baeder ASSERT_FALSE(GlobalDesc->isCompositeArray()); 59a07aba5dSTimm Baeder ASSERT_FALSE(GlobalDesc->isZeroSizeArray()); 60a07aba5dSTimm Baeder ASSERT_FALSE(GlobalDesc->isUnknownSizeArray()); 61a07aba5dSTimm Baeder ASSERT_FALSE(GlobalDesc->isPrimitive()); 62a07aba5dSTimm Baeder ASSERT_FALSE(GlobalDesc->isArray()); 63a07aba5dSTimm Baeder ASSERT_TRUE(GlobalDesc->isRecord()); 64a07aba5dSTimm Baeder 65a07aba5dSTimm Baeder // Test the Record for the struct S. 66a07aba5dSTimm Baeder const Record *SRecord = GlobalDesc->ElemRecord; 67a07aba5dSTimm Baeder ASSERT_TRUE(SRecord); 68a07aba5dSTimm Baeder ASSERT_TRUE(SRecord->getNumFields() == 5); 69a07aba5dSTimm Baeder ASSERT_TRUE(SRecord->getNumBases() == 0); 70a07aba5dSTimm Baeder ASSERT_FALSE(SRecord->getDestructor()); 71a07aba5dSTimm Baeder 72a07aba5dSTimm Baeder // First field. 73a07aba5dSTimm Baeder const Record::Field *F1 = SRecord->getField(0u); 74a07aba5dSTimm Baeder ASSERT_TRUE(F1); 75a07aba5dSTimm Baeder ASSERT_FALSE(F1->isBitField()); 76a07aba5dSTimm Baeder ASSERT_TRUE(F1->Desc->isPrimitive()); 77a07aba5dSTimm Baeder 78a07aba5dSTimm Baeder // Second field. 79a07aba5dSTimm Baeder const Record::Field *F2 = SRecord->getField(1u); 80a07aba5dSTimm Baeder ASSERT_TRUE(F2); 81a07aba5dSTimm Baeder ASSERT_FALSE(F2->isBitField()); 82a07aba5dSTimm Baeder ASSERT_TRUE(F2->Desc->isArray()); 83a07aba5dSTimm Baeder ASSERT_FALSE(F2->Desc->isCompositeArray()); 84a07aba5dSTimm Baeder ASSERT_TRUE(F2->Desc->isPrimitiveArray()); 85a07aba5dSTimm Baeder ASSERT_FALSE(F2->Desc->isPrimitive()); 86a07aba5dSTimm Baeder ASSERT_FALSE(F2->Desc->ElemDesc); 87a07aba5dSTimm Baeder ASSERT_EQ(F2->Desc->getNumElems(), 4u); 88a07aba5dSTimm Baeder ASSERT_TRUE(F2->Desc->getElemSize() > 0); 89a07aba5dSTimm Baeder 90a07aba5dSTimm Baeder // Third field. 91a07aba5dSTimm Baeder const Record::Field *F3 = SRecord->getField(2u); 92a07aba5dSTimm Baeder ASSERT_TRUE(F3); 93a07aba5dSTimm Baeder ASSERT_FALSE(F3->isBitField()); 94a07aba5dSTimm Baeder ASSERT_TRUE(F3->Desc->isArray()); 95a07aba5dSTimm Baeder ASSERT_TRUE(F3->Desc->isCompositeArray()); 96a07aba5dSTimm Baeder ASSERT_FALSE(F3->Desc->isPrimitiveArray()); 97a07aba5dSTimm Baeder ASSERT_FALSE(F3->Desc->isPrimitive()); 98a07aba5dSTimm Baeder ASSERT_TRUE(F3->Desc->ElemDesc); 99a07aba5dSTimm Baeder ASSERT_EQ(F3->Desc->getNumElems(), 3u); 100a07aba5dSTimm Baeder ASSERT_TRUE(F3->Desc->getElemSize() > 0); 101a07aba5dSTimm Baeder 102a07aba5dSTimm Baeder // Fourth field. 103a07aba5dSTimm Baeder // Multidimensional arrays are treated as composite arrays, even 104a07aba5dSTimm Baeder // if the value type is primitive. 105a07aba5dSTimm Baeder const Record::Field *F4 = SRecord->getField(3u); 106a07aba5dSTimm Baeder ASSERT_TRUE(F4); 107a07aba5dSTimm Baeder ASSERT_FALSE(F4->isBitField()); 108a07aba5dSTimm Baeder ASSERT_TRUE(F4->Desc->isArray()); 109a07aba5dSTimm Baeder ASSERT_TRUE(F4->Desc->isCompositeArray()); 110a07aba5dSTimm Baeder ASSERT_FALSE(F4->Desc->isPrimitiveArray()); 111a07aba5dSTimm Baeder ASSERT_FALSE(F4->Desc->isPrimitive()); 112a07aba5dSTimm Baeder ASSERT_TRUE(F4->Desc->ElemDesc); 113a07aba5dSTimm Baeder ASSERT_EQ(F4->Desc->getNumElems(), 3u); 114a07aba5dSTimm Baeder ASSERT_TRUE(F4->Desc->getElemSize() > 0); 115a07aba5dSTimm Baeder ASSERT_TRUE(F4->Desc->ElemDesc->isPrimitiveArray()); 116a07aba5dSTimm Baeder 117a07aba5dSTimm Baeder // Fifth field. Zero-size array. 118a07aba5dSTimm Baeder const Record::Field *F5 = SRecord->getField(4u); 119a07aba5dSTimm Baeder ASSERT_TRUE(F5); 120a07aba5dSTimm Baeder ASSERT_FALSE(F5->isBitField()); 121a07aba5dSTimm Baeder ASSERT_TRUE(F5->Desc->isArray()); 122a07aba5dSTimm Baeder ASSERT_FALSE(F5->Desc->isCompositeArray()); 123a07aba5dSTimm Baeder ASSERT_TRUE(F5->Desc->isPrimitiveArray()); 124a07aba5dSTimm Baeder ASSERT_FALSE(F5->Desc->isPrimitive()); 125a07aba5dSTimm Baeder ASSERT_EQ(F5->Desc->getNumElems(), 0u); 126a07aba5dSTimm Baeder 127a07aba5dSTimm Baeder // Check pointer stuff. 128a07aba5dSTimm Baeder // Global variables have an inline descriptor. 129a07aba5dSTimm Baeder ASSERT_TRUE(GlobalPtr.isRoot()); 130a07aba5dSTimm Baeder ASSERT_TRUE(GlobalPtr.isLive()); 131a07aba5dSTimm Baeder ASSERT_FALSE(GlobalPtr.isZero()); 132a07aba5dSTimm Baeder ASSERT_FALSE(GlobalPtr.isField()); 133a07aba5dSTimm Baeder ASSERT_TRUE(GlobalPtr.getFieldDesc() == GlobalPtr.getDeclDesc()); 134a07aba5dSTimm Baeder ASSERT_TRUE(GlobalPtr.getOffset() == 0); 135a07aba5dSTimm Baeder ASSERT_FALSE(GlobalPtr.inArray()); 136a07aba5dSTimm Baeder ASSERT_FALSE(GlobalPtr.isArrayElement()); 137a07aba5dSTimm Baeder ASSERT_FALSE(GlobalPtr.isArrayRoot()); 138a07aba5dSTimm Baeder ASSERT_FALSE(GlobalPtr.inPrimitiveArray()); 139a07aba5dSTimm Baeder ASSERT_TRUE(GlobalPtr.isStatic()); 140a07aba5dSTimm Baeder ASSERT_TRUE(GlobalPtr.isInitialized()); 141a07aba5dSTimm Baeder ASSERT_FALSE(GlobalPtr.isOnePastEnd()); 142a07aba5dSTimm Baeder ASSERT_FALSE(GlobalPtr.isElementPastEnd()); 143a07aba5dSTimm Baeder 144a07aba5dSTimm Baeder // Pointer to the first field (a primitive). 145a07aba5dSTimm Baeder const Pointer &PF1 = GlobalPtr.atField(F1->Offset); 146a07aba5dSTimm Baeder ASSERT_TRUE(PF1.isLive()); 147a07aba5dSTimm Baeder ASSERT_TRUE(PF1.isInitialized()); 148a07aba5dSTimm Baeder ASSERT_TRUE(PF1.isField()); 149a07aba5dSTimm Baeder ASSERT_FALSE(PF1.inArray()); 150a07aba5dSTimm Baeder ASSERT_FALSE(PF1.isArrayElement()); 151a07aba5dSTimm Baeder ASSERT_FALSE(PF1.isArrayRoot()); 152a07aba5dSTimm Baeder ASSERT_FALSE(PF1.isOnePastEnd()); 153a07aba5dSTimm Baeder ASSERT_FALSE(PF1.isRoot()); 154a07aba5dSTimm Baeder ASSERT_TRUE(PF1.getFieldDesc()->isPrimitive()); 155a07aba5dSTimm Baeder ASSERT_TRUE(Pointer::hasSameBase(PF1, GlobalPtr)); 156a07aba5dSTimm Baeder ASSERT_TRUE(PF1.getBase() == GlobalPtr); 157a07aba5dSTimm Baeder 158a07aba5dSTimm Baeder // Pointer to the second field (a primitive array). 159a07aba5dSTimm Baeder const Pointer &PF2 = GlobalPtr.atField(F2->Offset); 160a07aba5dSTimm Baeder ASSERT_TRUE(PF2.isLive()); 161a07aba5dSTimm Baeder ASSERT_TRUE(PF2.isInitialized()); 162a07aba5dSTimm Baeder ASSERT_TRUE(PF2.isField()); 163a07aba5dSTimm Baeder ASSERT_TRUE(PF2.inArray()); 164a07aba5dSTimm Baeder ASSERT_FALSE(PF2.isArrayElement()); 165a07aba5dSTimm Baeder ASSERT_TRUE(PF2.isArrayRoot()); 166a07aba5dSTimm Baeder ASSERT_TRUE(PF2.getNumElems() == 4); 167a07aba5dSTimm Baeder ASSERT_FALSE(PF2.isOnePastEnd()); 168a07aba5dSTimm Baeder ASSERT_FALSE(PF2.isRoot()); 169a07aba5dSTimm Baeder ASSERT_FALSE(PF2.getFieldDesc()->isPrimitive()); 170a07aba5dSTimm Baeder ASSERT_TRUE(PF2.getFieldDesc()->isArray()); 171a07aba5dSTimm Baeder ASSERT_TRUE(Pointer::hasSameBase(PF2, GlobalPtr)); 172a07aba5dSTimm Baeder ASSERT_TRUE(PF2.getBase() == GlobalPtr); 173a07aba5dSTimm Baeder 174a07aba5dSTimm Baeder // Check contents of field 2 (a primitive array). 175a07aba5dSTimm Baeder { 176a07aba5dSTimm Baeder const Pointer &E1 = PF2.atIndex(0); 177a07aba5dSTimm Baeder ASSERT_TRUE(E1.isLive()); 178a07aba5dSTimm Baeder ASSERT_FALSE(E1.isArrayRoot()); 179a07aba5dSTimm Baeder ASSERT_TRUE(E1.isArrayElement()); 180a07aba5dSTimm Baeder ASSERT_TRUE(E1.inPrimitiveArray()); 181a07aba5dSTimm Baeder ASSERT_TRUE(E1.deref<char>() == 'f'); 182a07aba5dSTimm Baeder ASSERT_EQ(E1.getIndex(), 0u); 183a07aba5dSTimm Baeder ASSERT_TRUE(E1 == E1.atIndex(0)); 184a07aba5dSTimm Baeder ASSERT_TRUE(Pointer::hasSameBase(E1, GlobalPtr)); 185a07aba5dSTimm Baeder 186a07aba5dSTimm Baeder const Pointer &E2 = PF2.atIndex(1); 187a07aba5dSTimm Baeder ASSERT_TRUE(E2.isLive()); 188a07aba5dSTimm Baeder ASSERT_FALSE(E2.isArrayRoot()); 189a07aba5dSTimm Baeder ASSERT_TRUE(E2.isArrayElement()); 190a07aba5dSTimm Baeder ASSERT_EQ(E2.getIndex(), 1u); 191a07aba5dSTimm Baeder // Narrow() doesn't do anything on primitive array elements, as there is 192a07aba5dSTimm Baeder // nothing to narrow into. 193a07aba5dSTimm Baeder ASSERT_EQ(E2.narrow(), E2); 194a07aba5dSTimm Baeder // ... so this should also hold. 195a07aba5dSTimm Baeder ASSERT_EQ(E2.expand(), E2); 196a07aba5dSTimm Baeder ASSERT_EQ(E2.narrow().expand(), E2); 197a07aba5dSTimm Baeder 198a07aba5dSTimm Baeder // .atIndex(1).atIndex(1) should be index 1. 199a07aba5dSTimm Baeder ASSERT_EQ(PF2.atIndex(1).atIndex(1), PF2.atIndex(1)); 200a07aba5dSTimm Baeder ASSERT_EQ(PF2.atIndex(1).narrow().atIndex(1), PF2.atIndex(1)); 201a07aba5dSTimm Baeder 202a07aba5dSTimm Baeder // getArray() should give us the array field again. 203a07aba5dSTimm Baeder ASSERT_EQ(E2.getArray(), PF2); 204a07aba5dSTimm Baeder 205a07aba5dSTimm Baeder // One-after-the-end pointer. 206a07aba5dSTimm Baeder const Pointer &O = PF2.atIndex(PF2.getNumElems()); 207a07aba5dSTimm Baeder ASSERT_TRUE(O.isLive()); 208a07aba5dSTimm Baeder ASSERT_TRUE(O.isOnePastEnd()); 209a07aba5dSTimm Baeder ASSERT_TRUE(O.isInitialized()); 210a07aba5dSTimm Baeder ASSERT_TRUE(O.getIndex() == PF2.getNumElems()); 211a07aba5dSTimm Baeder } 212a07aba5dSTimm Baeder 213a07aba5dSTimm Baeder // Pointer to the third field (a composite array). 214a07aba5dSTimm Baeder const Pointer &PF3 = GlobalPtr.atField(F3->Offset); 215a07aba5dSTimm Baeder ASSERT_TRUE(PF3.isLive()); 216a07aba5dSTimm Baeder ASSERT_TRUE(PF3.isInitialized()); 217a07aba5dSTimm Baeder ASSERT_TRUE(PF3.isField()); 218a07aba5dSTimm Baeder ASSERT_TRUE(PF3.inArray()); 219a07aba5dSTimm Baeder ASSERT_TRUE(PF3.isArrayRoot()); 220a07aba5dSTimm Baeder ASSERT_FALSE(PF3.isArrayElement()); 221a07aba5dSTimm Baeder ASSERT_TRUE(PF3.getNumElems() == 3); 222a07aba5dSTimm Baeder ASSERT_FALSE(PF3.isOnePastEnd()); 223a07aba5dSTimm Baeder ASSERT_FALSE(PF3.isRoot()); 224a07aba5dSTimm Baeder ASSERT_FALSE(PF3.getFieldDesc()->isPrimitive()); 225a07aba5dSTimm Baeder ASSERT_TRUE(PF3.getFieldDesc()->isArray()); 226a07aba5dSTimm Baeder ASSERT_TRUE(Pointer::hasSameBase(PF3, GlobalPtr)); 227a07aba5dSTimm Baeder ASSERT_TRUE(PF3.getBase() == GlobalPtr); 228a07aba5dSTimm Baeder ASSERT_EQ(PF3.getRecord(), nullptr); 229a07aba5dSTimm Baeder ASSERT_TRUE(PF3.getElemRecord()); 230a07aba5dSTimm Baeder 231a07aba5dSTimm Baeder // Check contents of field 3 (a composite array). 232a07aba5dSTimm Baeder { 233a07aba5dSTimm Baeder const Pointer &E1 = PF3.atIndex(0); 234a07aba5dSTimm Baeder // Note that we didn't call narrow() above, so this points 235a07aba5dSTimm Baeder // to an array element and not just a field. 236a07aba5dSTimm Baeder ASSERT_TRUE(E1.isLive()); 237a07aba5dSTimm Baeder ASSERT_EQ(E1.getIndex(), 0); 238a07aba5dSTimm Baeder ASSERT_TRUE(E1.isInitialized()); 239a07aba5dSTimm Baeder ASSERT_TRUE(E1.isArrayElement()); 240a07aba5dSTimm Baeder ASSERT_TRUE(E1.inArray()); 241a07aba5dSTimm Baeder ASSERT_FALSE(E1.isArrayRoot()); 242a07aba5dSTimm Baeder ASSERT_FALSE(E1.isRoot()); 243a07aba5dSTimm Baeder ASSERT_EQ(E1.getArray(), PF3); 244a07aba5dSTimm Baeder ASSERT_TRUE(E1.isField()); 245a07aba5dSTimm Baeder ASSERT_TRUE(E1.getElemRecord()); 246a07aba5dSTimm Baeder ASSERT_FALSE(E1.getRecord()); 247a07aba5dSTimm Baeder 248a07aba5dSTimm Baeder // Now the same with narrow(). 249a07aba5dSTimm Baeder const Pointer &NE1 = PF3.atIndex(0).narrow(); 250a07aba5dSTimm Baeder ASSERT_NE(E1, NE1); 251a07aba5dSTimm Baeder ASSERT_TRUE(NE1.isLive()); 252a07aba5dSTimm Baeder ASSERT_EQ(NE1.getIndex(), 0); 253a07aba5dSTimm Baeder ASSERT_TRUE(NE1.isInitialized()); 254*800b0739STimm Baeder ASSERT_TRUE(NE1.isArrayElement()); 255a07aba5dSTimm Baeder ASSERT_TRUE(NE1.isField()); 256a07aba5dSTimm Baeder ASSERT_FALSE(NE1.inArray()); 257a07aba5dSTimm Baeder ASSERT_FALSE(NE1.isArrayRoot()); 258a07aba5dSTimm Baeder ASSERT_FALSE(NE1.isRoot()); 259a07aba5dSTimm Baeder // Not possible, since this is narrow()ed: 260a07aba5dSTimm Baeder // ASSERT_EQ(NE1.getArray(), PF3); 261a07aba5dSTimm Baeder ASSERT_EQ(NE1.expand(), E1); 262a07aba5dSTimm Baeder ASSERT_FALSE(NE1.getElemRecord()); 263a07aba5dSTimm Baeder ASSERT_TRUE(NE1.getRecord()); 264a07aba5dSTimm Baeder 265a07aba5dSTimm Baeder // Second element, NOT narrowed. 266a07aba5dSTimm Baeder const Pointer &E2 = PF3.atIndex(1); 267a07aba5dSTimm Baeder ASSERT_TRUE(E2.isLive()); 268a07aba5dSTimm Baeder ASSERT_EQ(E2.getIndex(), 1); 269a07aba5dSTimm Baeder ASSERT_TRUE(E2.isInitialized()); 270a07aba5dSTimm Baeder ASSERT_TRUE(E2.isArrayElement()); 271a07aba5dSTimm Baeder ASSERT_TRUE(E2.isField()); 272a07aba5dSTimm Baeder ASSERT_TRUE(E2.inArray()); 273a07aba5dSTimm Baeder ASSERT_FALSE(E2.isArrayRoot()); 274a07aba5dSTimm Baeder ASSERT_FALSE(E2.isRoot()); 275a07aba5dSTimm Baeder ASSERT_EQ(E2.getArray(), PF3); 276a07aba5dSTimm Baeder 277a07aba5dSTimm Baeder // Second element, narrowed. 278a07aba5dSTimm Baeder const Pointer &NE2 = PF3.atIndex(1).narrow(); 279a07aba5dSTimm Baeder ASSERT_TRUE(NE2.isLive()); 280a07aba5dSTimm Baeder ASSERT_EQ(NE2.getIndex(), 0); 281a07aba5dSTimm Baeder ASSERT_TRUE(NE2.isInitialized()); 282*800b0739STimm Baeder ASSERT_TRUE(NE2.isArrayElement()); 283a07aba5dSTimm Baeder ASSERT_TRUE(NE2.isField()); 284a07aba5dSTimm Baeder ASSERT_FALSE(NE2.inArray()); 285a07aba5dSTimm Baeder ASSERT_FALSE(NE2.isArrayRoot()); 286a07aba5dSTimm Baeder ASSERT_FALSE(NE2.isRoot()); 287a07aba5dSTimm Baeder // Not possible, since this is narrow()ed: 288a07aba5dSTimm Baeder // ASSERT_EQ(NE2.getArray(), PF3); 289a07aba5dSTimm Baeder ASSERT_FALSE(NE2.getElemRecord()); 290a07aba5dSTimm Baeder ASSERT_TRUE(NE2.getRecord()); 291a07aba5dSTimm Baeder 292a07aba5dSTimm Baeder // Chained atIndex() without narrowing in between. 293a07aba5dSTimm Baeder ASSERT_EQ(PF3.atIndex(1).atIndex(1), PF3.atIndex(1)); 294a07aba5dSTimm Baeder 295a07aba5dSTimm Baeder // First field of the second element. 296a07aba5dSTimm Baeder const Pointer &FP1 = NE2.atField(NE2.getRecord()->getField(0u)->Offset); 297a07aba5dSTimm Baeder ASSERT_TRUE(FP1.isLive()); 298a07aba5dSTimm Baeder ASSERT_TRUE(FP1.isInitialized()); 299a07aba5dSTimm Baeder ASSERT_EQ(FP1.getBase(), NE2); 300a07aba5dSTimm Baeder ASSERT_FALSE(FP1.isArrayElement()); 301a07aba5dSTimm Baeder ASSERT_FALSE(FP1.inArray()); 302a07aba5dSTimm Baeder ASSERT_FALSE(FP1.inPrimitiveArray()); 303a07aba5dSTimm Baeder ASSERT_TRUE(FP1.isField()); 304a07aba5dSTimm Baeder 305a07aba5dSTimm Baeder // One-past-the-end of a composite array. 306a07aba5dSTimm Baeder const Pointer &O = PF3.atIndex(PF3.getNumElems()).narrow(); 307a07aba5dSTimm Baeder ASSERT_TRUE(O.isOnePastEnd()); 308a07aba5dSTimm Baeder ASSERT_TRUE(O.isElementPastEnd()); 309a07aba5dSTimm Baeder } 310a07aba5dSTimm Baeder 311a07aba5dSTimm Baeder // Pointer to the fourth field (a multidimensional primitive array). 312a07aba5dSTimm Baeder const Pointer &PF4 = GlobalPtr.atField(F4->Offset); 313a07aba5dSTimm Baeder ASSERT_TRUE(PF4.isLive()); 314a07aba5dSTimm Baeder ASSERT_TRUE(PF4.isInitialized()); 315a07aba5dSTimm Baeder ASSERT_TRUE(PF4.isField()); 316a07aba5dSTimm Baeder ASSERT_TRUE(PF4.inArray()); 317a07aba5dSTimm Baeder ASSERT_TRUE(PF4.isArrayRoot()); 318a07aba5dSTimm Baeder ASSERT_FALSE(PF4.isArrayElement()); 319a07aba5dSTimm Baeder ASSERT_TRUE(PF4.getNumElems() == 3); 320a07aba5dSTimm Baeder ASSERT_FALSE(PF4.isOnePastEnd()); 321a07aba5dSTimm Baeder ASSERT_FALSE(PF4.isRoot()); 322a07aba5dSTimm Baeder ASSERT_FALSE(PF4.getFieldDesc()->isPrimitive()); 323a07aba5dSTimm Baeder ASSERT_TRUE(PF4.getFieldDesc()->isArray()); 324a07aba5dSTimm Baeder ASSERT_TRUE(Pointer::hasSameBase(PF4, GlobalPtr)); 325a07aba5dSTimm Baeder ASSERT_TRUE(PF4.getBase() == GlobalPtr); 326a07aba5dSTimm Baeder ASSERT_EQ(PF4.getRecord(), nullptr); 327a07aba5dSTimm Baeder ASSERT_EQ(PF4.getElemRecord(), nullptr); 328a07aba5dSTimm Baeder ASSERT_NE(PF4.getField(), nullptr); 329a07aba5dSTimm Baeder ASSERT_TRUE(PF4.getFieldDesc()->ElemDesc->isPrimitiveArray()); 330a07aba5dSTimm Baeder // Check contents of field 4 (a primitive array). 331a07aba5dSTimm Baeder { 332a07aba5dSTimm Baeder // Pointer to the first element, is of type short[3]. 333a07aba5dSTimm Baeder const Pointer &E1 = PF4.atIndex(0); 334a07aba5dSTimm Baeder ASSERT_NE(E1, PF4); 335a07aba5dSTimm Baeder ASSERT_TRUE(E1.isLive()); 336a07aba5dSTimm Baeder ASSERT_TRUE(E1.isArrayElement()); 337a07aba5dSTimm Baeder ASSERT_TRUE(E1.inArray()); 338a07aba5dSTimm Baeder ASSERT_EQ(E1.getNumElems(), 3u); 339a07aba5dSTimm Baeder ASSERT_EQ(E1.getIndex(), 0u); 340a07aba5dSTimm Baeder ASSERT_EQ(E1.getArray(), PF4); 341a07aba5dSTimm Baeder 342a07aba5dSTimm Baeder // Now narrow()'ed. 343a07aba5dSTimm Baeder const Pointer &NE1 = PF4.atIndex(0).narrow(); 344a07aba5dSTimm Baeder ASSERT_NE(NE1, PF4); 345a07aba5dSTimm Baeder ASSERT_NE(NE1, E1); 346a07aba5dSTimm Baeder ASSERT_TRUE(NE1.isLive()); 347*800b0739STimm Baeder ASSERT_TRUE(NE1.isArrayElement()); 348a07aba5dSTimm Baeder ASSERT_TRUE(NE1.isArrayRoot()); 349a07aba5dSTimm Baeder ASSERT_FALSE(NE1.getFieldDesc()->isCompositeArray()); 350a07aba5dSTimm Baeder ASSERT_TRUE(NE1.getFieldDesc()->isPrimitiveArray()); 351a07aba5dSTimm Baeder ASSERT_EQ(NE1.getFieldDesc()->getNumElems(), 3u); 352a07aba5dSTimm Baeder ASSERT_TRUE(NE1.inArray()); 353a07aba5dSTimm Baeder ASSERT_EQ(NE1.getNumElems(), 3u); 354a07aba5dSTimm Baeder ASSERT_EQ(NE1.getIndex(), 0u); 355a07aba5dSTimm Baeder 356a07aba5dSTimm Baeder // Last element of the first dimension. 357a07aba5dSTimm Baeder const Pointer &PE1 = PF4.atIndex(0).narrow().atIndex(2); 358a07aba5dSTimm Baeder ASSERT_TRUE(PE1.isLive()); 359a07aba5dSTimm Baeder ASSERT_EQ(PE1.deref<short>(), 3); 360a07aba5dSTimm Baeder ASSERT_EQ(PE1.getArray(), NE1); 361a07aba5dSTimm Baeder ASSERT_EQ(PE1.getIndex(), 2u); 362a07aba5dSTimm Baeder 363a07aba5dSTimm Baeder // third dimension 364a07aba5dSTimm Baeder const Pointer &E3 = PF4.atIndex(2); 365a07aba5dSTimm Baeder ASSERT_NE(E3, PF4); 366a07aba5dSTimm Baeder ASSERT_TRUE(E3.isLive()); 367a07aba5dSTimm Baeder ASSERT_TRUE(E3.isArrayElement()); 368a07aba5dSTimm Baeder ASSERT_FALSE(E3.isArrayRoot()); 369a07aba5dSTimm Baeder ASSERT_TRUE(E3.inArray()); 370a07aba5dSTimm Baeder ASSERT_EQ(E3.getNumElems(), 3u); 371a07aba5dSTimm Baeder ASSERT_EQ(E3.getIndex(), 2u); 372a07aba5dSTimm Baeder 373a07aba5dSTimm Baeder // Same, but narrow()'ed. 374a07aba5dSTimm Baeder const Pointer &NE3 = PF4.atIndex(2).narrow(); 375a07aba5dSTimm Baeder ASSERT_NE(NE3, PF4); 376a07aba5dSTimm Baeder ASSERT_NE(NE3, E1); 377a07aba5dSTimm Baeder ASSERT_TRUE(NE3.isLive()); 378*800b0739STimm Baeder ASSERT_TRUE(NE3.isArrayElement()); 379a07aba5dSTimm Baeder ASSERT_TRUE(NE3.isArrayRoot()); 380a07aba5dSTimm Baeder ASSERT_FALSE(NE3.getFieldDesc()->isCompositeArray()); 381a07aba5dSTimm Baeder ASSERT_TRUE(NE3.getFieldDesc()->isPrimitiveArray()); 382a07aba5dSTimm Baeder ASSERT_EQ(NE3.getFieldDesc()->getNumElems(), 3u); 383a07aba5dSTimm Baeder ASSERT_TRUE(NE3.inArray()); 384a07aba5dSTimm Baeder ASSERT_EQ(NE3.getNumElems(), 3u); 385a07aba5dSTimm Baeder // This is narrow()'ed, so not an "array elemnet" 386a07aba5dSTimm Baeder ASSERT_EQ(PF4.atIndex(2).getIndex(), 2u); 387a07aba5dSTimm Baeder ASSERT_EQ(NE3.getIndex(), 0u); 388a07aba5dSTimm Baeder 389a07aba5dSTimm Baeder // Last element of the last dimension 390a07aba5dSTimm Baeder const Pointer &PE3 = PF4.atIndex(2).narrow().atIndex(2); 391a07aba5dSTimm Baeder ASSERT_TRUE(PE3.isLive()); 392a07aba5dSTimm Baeder ASSERT_EQ(PE3.deref<short>(), 9); 393a07aba5dSTimm Baeder ASSERT_EQ(PE3.getArray(), NE3); 394a07aba5dSTimm Baeder ASSERT_EQ(PE3.getIndex(), 2u); 395a07aba5dSTimm Baeder } 396a07aba5dSTimm Baeder 397a07aba5dSTimm Baeder // Zero-size array. 398a07aba5dSTimm Baeder { 399a07aba5dSTimm Baeder const Pointer &PF5 = GlobalPtr.atField(F5->Offset); 400a07aba5dSTimm Baeder 401a07aba5dSTimm Baeder ASSERT_TRUE(PF5.isZeroSizeArray()); 402a07aba5dSTimm Baeder ASSERT_FALSE(PF5.isOnePastEnd()); 403a07aba5dSTimm Baeder ASSERT_FALSE(PF5.isElementPastEnd()); 404a07aba5dSTimm Baeder } 405a07aba5dSTimm Baeder } 406