Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(47)

Unified Diff: tools/clang/blink_gc_plugin/CheckFieldsVisitor.cpp

Issue 1385193002: Bisect clang Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: 246985 Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: tools/clang/blink_gc_plugin/CheckFieldsVisitor.cpp
diff --git a/tools/clang/blink_gc_plugin/CheckFieldsVisitor.cpp b/tools/clang/blink_gc_plugin/CheckFieldsVisitor.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0ed953fccf92e57197fcb7cc54a99bff36b8a675
--- /dev/null
+++ b/tools/clang/blink_gc_plugin/CheckFieldsVisitor.cpp
@@ -0,0 +1,152 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "CheckFieldsVisitor.h"
+
+#include <cassert>
+
+#include "BlinkGCPluginOptions.h"
+#include "RecordInfo.h"
+
+CheckFieldsVisitor::CheckFieldsVisitor(const BlinkGCPluginOptions& options)
+ : options_(options),
+ current_(0),
+ stack_allocated_host_(false) {
+}
+
+CheckFieldsVisitor::Errors& CheckFieldsVisitor::invalid_fields() {
+ return invalid_fields_;
+}
+
+bool CheckFieldsVisitor::ContainsInvalidFields(RecordInfo* info) {
+ stack_allocated_host_ = info->IsStackAllocated();
+ managed_host_ = stack_allocated_host_ ||
+ info->IsGCAllocated() ||
+ info->IsNonNewable() ||
+ info->IsOnlyPlacementNewable();
+ for (RecordInfo::Fields::iterator it = info->GetFields().begin();
+ it != info->GetFields().end();
+ ++it) {
+ context().clear();
+ current_ = &it->second;
+ current_->edge()->Accept(this);
+ }
+ return !invalid_fields_.empty();
+}
+
+void CheckFieldsVisitor::AtMember(Member* edge) {
+ if (managed_host_)
+ return;
+ // A member is allowed to appear in the context of a root.
+ for (Context::iterator it = context().begin();
+ it != context().end();
+ ++it) {
+ if ((*it)->Kind() == Edge::kRoot)
+ return;
+ }
+ invalid_fields_.push_back(std::make_pair(current_, kMemberInUnmanaged));
+}
+
+void CheckFieldsVisitor::AtValue(Value* edge) {
+ // TODO: what should we do to check unions?
+ if (edge->value()->record()->isUnion())
+ return;
+
+ if (!stack_allocated_host_ && edge->value()->IsStackAllocated()) {
+ invalid_fields_.push_back(std::make_pair(current_, kPtrFromHeapToStack));
+ return;
+ }
+
+ if (!Parent() &&
+ edge->value()->IsGCDerived() &&
+ !edge->value()->IsGCMixin()) {
+ invalid_fields_.push_back(std::make_pair(current_, kGCDerivedPartObject));
+ return;
+ }
+
+ // If in a stack allocated context, be fairly insistent that T in Member<T>
+ // is GC allocated, as stack allocated objects do not have a trace()
+ // that separately verifies the validity of Member<T>.
+ //
+ // Notice that an error is only reported if T's definition is in scope;
+ // we do not require that it must be brought into scope as that would
+ // prevent declarations of mutually dependent class types.
+ //
+ // (Note: Member<>'s constructor will at run-time verify that the
+ // pointer it wraps is indeed heap allocated.)
+ if (stack_allocated_host_ && Parent() && Parent()->IsMember() &&
+ edge->value()->HasDefinition() && !edge->value()->IsGCAllocated()) {
+ invalid_fields_.push_back(std::make_pair(current_,
+ kMemberToGCUnmanaged));
+ return;
+ }
+
+ if (!Parent() || !edge->value()->IsGCAllocated())
+ return;
+
+ // In transition mode, disallow OwnPtr<T>, RawPtr<T> to GC allocated T's,
+ // also disallow T* in stack-allocated types.
+ if (options_.enable_oilpan) {
+ if (Parent()->IsOwnPtr() ||
+ Parent()->IsRawPtrClass() ||
+ (stack_allocated_host_ && Parent()->IsRawPtr())) {
+ invalid_fields_.push_back(std::make_pair(
+ current_, InvalidSmartPtr(Parent())));
+ return;
+ }
+ if (options_.warn_raw_ptr && Parent()->IsRawPtr()) {
+ if (static_cast<RawPtr*>(Parent())->HasReferenceType()) {
+ invalid_fields_.push_back(std::make_pair(
+ current_, kReferencePtrToGCManagedWarning));
+ } else {
+ invalid_fields_.push_back(std::make_pair(
+ current_, kRawPtrToGCManagedWarning));
+ }
+ }
+ return;
+ }
+
+ if (Parent()->IsRawPtr() || Parent()->IsRefPtr() || Parent()->IsOwnPtr()) {
+ invalid_fields_.push_back(std::make_pair(
+ current_, InvalidSmartPtr(Parent())));
+ return;
+ }
+}
+
+void CheckFieldsVisitor::AtCollection(Collection* edge) {
+ if (edge->on_heap() && Parent() && Parent()->IsOwnPtr())
+ invalid_fields_.push_back(std::make_pair(current_, kOwnPtrToGCManaged));
+}
+
+bool CheckFieldsVisitor::IsWarning(Error error) {
+ if (error == kRawPtrToGCManagedWarning)
+ return true;
+ if (error == kReferencePtrToGCManagedWarning)
+ return true;
+ return false;
+}
+
+bool CheckFieldsVisitor::IsRawPtrError(Error error) {
+ return (error == kRawPtrToGCManaged ||
+ error == kRawPtrToGCManagedWarning);
+}
+
+bool CheckFieldsVisitor::IsReferencePtrError(Error error) {
+ return (error == kReferencePtrToGCManaged ||
+ error == kReferencePtrToGCManagedWarning);
+}
+
+CheckFieldsVisitor::Error CheckFieldsVisitor::InvalidSmartPtr(Edge* ptr) {
+ if (ptr->IsRawPtr()) {
+ if (static_cast<RawPtr*>(ptr)->HasReferenceType())
+ return kReferencePtrToGCManaged;
+ else
+ return kRawPtrToGCManaged;
+ }
+ if (ptr->IsRefPtr())
+ return kRefPtrToGCManaged;
+ if (ptr->IsOwnPtr())
+ return kOwnPtrToGCManaged;
+ assert(false && "Unknown smart pointer kind");
+}
« no previous file with comments | « tools/clang/blink_gc_plugin/CheckFieldsVisitor.h ('k') | tools/clang/blink_gc_plugin/CheckFinalizerVisitor.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698