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); }
bool CheckFinalizerVisitor::VisitMemberExpr(MemberExpr* member) { FieldDecl* field = dyn_cast<FieldDecl>(member->getMemberDecl()); if (!field) return true; RecordInfo* info = cache_->Lookup(field->getParent()); if (!info) return true; RecordInfo::Fields::iterator it = info->GetFields().find(field); if (it == info->GetFields().end()) return true; if (seen_members_.find(member) != seen_members_.end()) return true; bool as_eagerly_finalized = false; if (blacklist_context_ && MightBeCollected(&it->second, &as_eagerly_finalized)) { finalized_fields_.push_back( Error(member, as_eagerly_finalized, &it->second)); seen_members_.insert(member); } return true; }
RecordInfo::Bases* RecordInfo::CollectBases() { // Compute the collection locally to avoid inconsistent states. Bases* bases = new Bases; if (!record_->hasDefinition()) return bases; for (CXXRecordDecl::base_class_iterator it = record_->bases_begin(); it != record_->bases_end(); ++it) { const CXXBaseSpecifier& spec = *it; RecordInfo* info = cache_->Lookup(spec.getType()); if (!info) continue; CXXRecordDecl* base = info->record(); TracingStatus status = info->InheritsTrace() ? TracingStatus::Needed() : TracingStatus::Unneeded(); bases->insert(std::make_pair(base, BasePoint(spec, info, status))); } return bases; }
void BlinkGCPluginConsumer::CheckTraceMethod( RecordInfo* parent, CXXMethodDecl* trace, Config::TraceMethodType trace_type) { // A trace method must not override any non-virtual trace methods. if (trace_type == Config::TRACE_METHOD) { for (RecordInfo::Bases::iterator it = parent->GetBases().begin(); it != parent->GetBases().end(); ++it) { RecordInfo* base = it->second.info(); if (CXXMethodDecl* other = base->InheritsNonVirtualTrace()) ReportOverriddenNonVirtualTrace(parent, trace, other); } } CheckTraceVisitor visitor(trace, parent, &cache_); visitor.TraverseCXXMethodDecl(trace); // Skip reporting if this trace method is a just delegate to // traceImpl (or traceAfterDispatchImpl) method. We will report on // CheckTraceMethod on traceImpl method. if (visitor.delegates_to_traceimpl()) return; for (RecordInfo::Bases::iterator it = parent->GetBases().begin(); it != parent->GetBases().end(); ++it) { if (!it->second.IsProperlyTraced()) ReportBaseRequiresTracing(parent, trace, it->first); } for (RecordInfo::Fields::iterator it = parent->GetFields().begin(); it != parent->GetFields().end(); ++it) { if (!it->second.IsProperlyTraced()) { // Discontinue once an untraced-field error is found. ReportFieldsRequireTracing(parent, trace); break; } } }
void BlinkGCPluginConsumer::CheckTracingMethod(CXXMethodDecl* method) { RecordInfo* parent = cache_.Lookup(method->getParent()); if (IsIgnored(parent)) return; // Check templated tracing methods by checking the template instantiations. // Specialized templates are handled as ordinary classes. if (ClassTemplateDecl* tmpl = parent->record()->getDescribedClassTemplate()) { for (ClassTemplateDecl::spec_iterator it = tmpl->spec_begin(); it != tmpl->spec_end(); ++it) { // Check trace using each template instantiation as the holder. if (Config::IsTemplateInstantiation(*it)) CheckTraceOrDispatchMethod(cache_.Lookup(*it), method); } return; } CheckTraceOrDispatchMethod(parent, method); }
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); }
bool operator()(const RecordInfo &lhs, const RecordInfo &rhs) { return lhs.role().roleID() < rhs.role().roleID(); }
bool operator()(const RecordInfo &lhs, const RecordInfo &rhs) { return lhs.arg1() < rhs.arg1(); }