return false;
}
+bool RecordInfo::IsTreeShared() {
+ if (Config::IsTreeSharedBase(name_))
+ return true;
+ if (!IsGCDerived())
+ return false;
+ for (CXXBasePaths::paths_iterator it = base_paths_->begin();
+ it != base_paths_->end();
+ ++it) {
+ // TreeShared is an immediate base of GCFinalized.
+ if (it->size() < 2) continue;
+ const CXXBasePathElement& elem = (*it)[it->size() - 2];
+ CXXRecordDecl* base = elem.Base->getType()->getAsCXXRecordDecl();
+ if (Config::IsTreeSharedBase(base->getName()))
+ return true;
+ }
+ return false;
+}
+
// A GC mixin is a class that inherits from a GC mixin base and has
-// has not yet been "mixed in" with another GC base class.
+// not yet been "mixed in" with another GC base class.
bool RecordInfo::IsGCMixin() {
if (!IsGCDerived() || base_paths_->begin() == base_paths_->end())
return false;
- // Get the last element of the first path.
- CXXBasePaths::paths_iterator it = base_paths_->begin();
- const CXXBasePathElement& elem = (*it)[it->size() - 1];
- CXXRecordDecl* base = elem.Base->getType()->getAsCXXRecordDecl();
- // If it is not a mixin base we are done.
- if (!Config::IsGCMixinBase(base->getName()))
- return false;
- // This is a mixin if there are no other paths to GC bases.
- return ++it == base_paths_->end();
+ for (CXXBasePaths::paths_iterator it = base_paths_->begin();
+ it != base_paths_->end();
+ ++it) {
+ // Get the last element of the path.
+ const CXXBasePathElement& elem = (*it)[it->size() - 1];
+ CXXRecordDecl* base = elem.Base->getType()->getAsCXXRecordDecl();
+ // If it is not a mixin base we are done.
+ if (!Config::IsGCMixinBase(base->getName()))
+ return false;
+ }
+ // This is a mixin if all GC bases are mixins.
+ return true;
}
// Test if a record is allocated on the managed heap.
return is_only_placement_newable_;
}
+CXXMethodDecl* RecordInfo::DeclaresNewOperator() {
+ for (CXXRecordDecl::method_iterator it = record_->method_begin();
+ it != record_->method_end();
+ ++it) {
+ if (it->getNameAsString() == kNewOperatorName && it->getNumParams() == 1)
+ return *it;
+ }
+ return 0;
+}
+
// An object requires a tracing method if it has any fields that need tracing.
bool RecordInfo::RequiresTraceMethod() {
if (IsStackAllocated())
if (type->isPointerType()) {
if (Edge* ptr = CreateEdge(type->getPointeeType().getTypePtrOrNull()))
- return new RawPtr(ptr);
+ return new RawPtr(ptr, false);
return 0;
}
if (Config::IsRawPtr(info->name()) && info->GetTemplateArgs(1, &args)) {
if (Edge* ptr = CreateEdge(args[0]))
- return new RawPtr(ptr);
+ return new RawPtr(ptr, true);
return 0;
}
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;
}
+ // 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;
}