Edge* RecordInfo::CreateEdgeFromOriginalType(const Type* type) { if (!type) return nullptr; // look for "typedef ... iterator;" if (!isa<ElaboratedType>(type)) return nullptr; const ElaboratedType* elaboratedType = cast<ElaboratedType>(type); if (!isa<TypedefType>(elaboratedType->getNamedType())) return nullptr; const TypedefType* typedefType = cast<TypedefType>(elaboratedType->getNamedType()); std::string typeName = typedefType->getDecl()->getNameAsString(); if (!Config::IsIterator(typeName)) return nullptr; RecordInfo* info = cache_->Lookup(elaboratedType->getQualifier()->getAsType()); bool on_heap = false; bool is_unsafe = false; // Silently handle unknown types; the on-heap collection types will // have to be in scope for the declaration to compile, though. if (info) { is_unsafe = Config::IsGCCollectionWithUnsafeIterator(info->name()); // Don't mark iterator as being on the heap if it is not supported. on_heap = !is_unsafe && Config::IsGCCollection(info->name()); } return new Iterator(info, on_heap, is_unsafe); }
Edge* RecordInfo::CreateEdge(const Type* type) { if (!type) { return 0; } if (type->isPointerType() || type->isReferenceType()) { if (Edge* ptr = CreateEdge(type->getPointeeType().getTypePtrOrNull())) return new RawPtr(ptr, false, type->isReferenceType()); return 0; } RecordInfo* info = cache_->Lookup(type); // If the type is neither a pointer or a C++ record we ignore it. if (!info) { return 0; } TemplateArgs args; if (Config::IsRawPtr(info->name()) && info->GetTemplateArgs(1, &args)) { if (Edge* ptr = CreateEdge(args[0])) return new RawPtr(ptr, true, false); return 0; } if (Config::IsRefPtr(info->name()) && info->GetTemplateArgs(1, &args)) { if (Edge* ptr = CreateEdge(args[0])) return new RefPtr(ptr); return 0; } if (Config::IsOwnPtr(info->name()) && info->GetTemplateArgs(1, &args)) { if (Edge* ptr = CreateEdge(args[0])) return new OwnPtr(ptr); return 0; } if (Config::IsMember(info->name()) && info->GetTemplateArgs(1, &args)) { if (Edge* ptr = CreateEdge(args[0])) return new Member(ptr); return 0; } if (Config::IsWeakMember(info->name()) && info->GetTemplateArgs(1, &args)) { if (Edge* ptr = CreateEdge(args[0])) return new WeakMember(ptr); return 0; } if (Config::IsPersistent(info->name())) { // Persistent might refer to v8::Persistent, so check the name space. // TODO: Consider using a more canonical identification than names. NamespaceDecl* ns = dyn_cast<NamespaceDecl>(info->record()->getDeclContext()); if (!ns || ns->getName() != "blink") return 0; if (!info->GetTemplateArgs(1, &args)) return 0; if (Edge* ptr = CreateEdge(args[0])) return new Persistent(ptr); return 0; } if (Config::IsGCCollection(info->name()) || Config::IsWTFCollection(info->name())) { bool is_root = Config::IsPersistentGCCollection(info->name()); bool on_heap = is_root || info->IsHeapAllocatedCollection(); size_t count = Config::CollectionDimension(info->name()); if (!info->GetTemplateArgs(count, &args)) return 0; Collection* edge = new Collection(info, on_heap, is_root); for (TemplateArgs::iterator it = args.begin(); it != args.end(); ++it) { if (Edge* member = CreateEdge(*it)) { edge->members().push_back(member); } // TODO: Handle the case where we fail to create an edge (eg, if the // argument is a primitive type or just not fully known yet). } return edge; } return new Value(info); }
Edge* RecordInfo::CreateEdge(const Type* type) { if (!type) { return 0; } if (type->isPointerType()) { if (Edge* ptr = CreateEdge(type->getPointeeType().getTypePtrOrNull())) return new RawPtr(ptr); return 0; } RecordInfo* info = cache_->Lookup(type); // If the type is neither a pointer or a C++ record we ignore it. if (!info) { return 0; } TemplateArgs args; if (Config::IsRawPtr(info->name()) && info->GetTemplateArgs(1, &args)) { if (Edge* ptr = CreateEdge(args[0])) return new RawPtr(ptr); return 0; } if (Config::IsRefPtr(info->name()) && info->GetTemplateArgs(1, &args)) { if (Edge* ptr = CreateEdge(args[0])) return new RefPtr(ptr); return 0; } if (Config::IsOwnPtr(info->name()) && info->GetTemplateArgs(1, &args)) { if (Edge* ptr = CreateEdge(args[0])) return new OwnPtr(ptr); return 0; } if (Config::IsMember(info->name()) && info->GetTemplateArgs(1, &args)) { if (Edge* ptr = CreateEdge(args[0])) return new Member(ptr); return 0; } if (Config::IsWeakMember(info->name()) && info->GetTemplateArgs(1, &args)) { if (Edge* ptr = CreateEdge(args[0])) return new WeakMember(ptr); return 0; } if (Config::IsPersistent(info->name())) { // Persistent might refer to v8::Persistent, so check the name space. // TODO: Consider using a more canonical identification than names. NamespaceDecl* ns = dyn_cast<NamespaceDecl>(info->record()->getDeclContext()); if (!ns || ns->getName() != "WebCore") return 0; if (!info->GetTemplateArgs(1, &args)) return 0; if (Edge* ptr = CreateEdge(args[0])) return new Persistent(ptr); return 0; } if (Config::IsGCCollection(info->name()) || Config::IsWTFCollection(info->name())) { bool is_root = Config::IsPersistentGCCollection(info->name()); bool on_heap = is_root || info->IsHeapAllocatedCollection(); size_t count = Config::CollectionDimension(info->name()); if (!info->GetTemplateArgs(count, &args)) return 0; Collection* edge = new Collection(info, on_heap, is_root); for (TemplateArgs::iterator it = args.begin(); it != args.end(); ++it) { if (Edge* member = CreateEdge(*it)) { edge->members().push_back(member); } else { // We failed to create an edge so abort the entire edge construction. delete edge; // Will delete the already allocated members. return 0; } } return edge; } return new Value(info); }