1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "CheckFieldsVisitor.h"
9 #include "BlinkGCPluginOptions.h"
10 #include "RecordInfo.h"
12 CheckFieldsVisitor::CheckFieldsVisitor(const BlinkGCPluginOptions
& options
)
15 stack_allocated_host_(false) {
18 CheckFieldsVisitor::Errors
& CheckFieldsVisitor::invalid_fields() {
19 return invalid_fields_
;
22 bool CheckFieldsVisitor::ContainsInvalidFields(RecordInfo
* info
) {
23 stack_allocated_host_
= info
->IsStackAllocated();
24 managed_host_
= stack_allocated_host_
||
25 info
->IsGCAllocated() ||
26 info
->IsNonNewable() ||
27 info
->IsOnlyPlacementNewable();
28 for (RecordInfo::Fields::iterator it
= info
->GetFields().begin();
29 it
!= info
->GetFields().end();
32 current_
= &it
->second
;
33 current_
->edge()->Accept(this);
35 return !invalid_fields_
.empty();
38 void CheckFieldsVisitor::AtMember(Member
* edge
) {
41 // A member is allowed to appear in the context of a root.
42 for (Context::iterator it
= context().begin();
43 it
!= context().end();
45 if ((*it
)->Kind() == Edge::kRoot
)
48 invalid_fields_
.push_back(std::make_pair(current_
, kMemberInUnmanaged
));
51 void CheckFieldsVisitor::AtValue(Value
* edge
) {
52 // TODO: what should we do to check unions?
53 if (edge
->value()->record()->isUnion())
56 if (!stack_allocated_host_
&& edge
->value()->IsStackAllocated()) {
57 invalid_fields_
.push_back(std::make_pair(current_
, kPtrFromHeapToStack
));
62 edge
->value()->IsGCDerived() &&
63 !edge
->value()->IsGCMixin()) {
64 invalid_fields_
.push_back(std::make_pair(current_
, kGCDerivedPartObject
));
68 // If in a stack allocated context, be fairly insistent that T in Member<T>
69 // is GC allocated, as stack allocated objects do not have a trace()
70 // that separately verifies the validity of Member<T>.
72 // Notice that an error is only reported if T's definition is in scope;
73 // we do not require that it must be brought into scope as that would
74 // prevent declarations of mutually dependent class types.
76 // (Note: Member<>'s constructor will at run-time verify that the
77 // pointer it wraps is indeed heap allocated.)
78 if (stack_allocated_host_
&& Parent() && Parent()->IsMember() &&
79 edge
->value()->HasDefinition() && !edge
->value()->IsGCAllocated()) {
80 invalid_fields_
.push_back(std::make_pair(current_
,
81 kMemberToGCUnmanaged
));
85 if (!Parent() || !edge
->value()->IsGCAllocated())
88 // In transition mode, disallow OwnPtr<T>, RawPtr<T> to GC allocated T's,
89 // also disallow T* in stack-allocated types.
90 if (options_
.enable_oilpan
) {
91 if (Parent()->IsOwnPtr() ||
92 Parent()->IsRawPtrClass() ||
93 (stack_allocated_host_
&& Parent()->IsRawPtr())) {
94 invalid_fields_
.push_back(std::make_pair(
95 current_
, InvalidSmartPtr(Parent())));
98 if (options_
.warn_raw_ptr
&& Parent()->IsRawPtr()) {
99 if (static_cast<RawPtr
*>(Parent())->HasReferenceType()) {
100 invalid_fields_
.push_back(std::make_pair(
101 current_
, kReferencePtrToGCManagedWarning
));
103 invalid_fields_
.push_back(std::make_pair(
104 current_
, kRawPtrToGCManagedWarning
));
110 if (Parent()->IsRawPtr() || Parent()->IsRefPtr() || Parent()->IsOwnPtr()) {
111 invalid_fields_
.push_back(std::make_pair(
112 current_
, InvalidSmartPtr(Parent())));
117 void CheckFieldsVisitor::AtCollection(Collection
* edge
) {
118 if (edge
->on_heap() && Parent() && Parent()->IsOwnPtr())
119 invalid_fields_
.push_back(std::make_pair(current_
, kOwnPtrToGCManaged
));
122 bool CheckFieldsVisitor::IsWarning(Error error
) {
123 if (error
== kRawPtrToGCManagedWarning
)
125 if (error
== kReferencePtrToGCManagedWarning
)
130 bool CheckFieldsVisitor::IsRawPtrError(Error error
) {
131 return (error
== kRawPtrToGCManaged
||
132 error
== kRawPtrToGCManagedWarning
);
135 bool CheckFieldsVisitor::IsReferencePtrError(Error error
) {
136 return (error
== kReferencePtrToGCManaged
||
137 error
== kReferencePtrToGCManagedWarning
);
140 CheckFieldsVisitor::Error
CheckFieldsVisitor::InvalidSmartPtr(Edge
* ptr
) {
141 if (ptr
->IsRawPtr()) {
142 if (static_cast<RawPtr
*>(ptr
)->HasReferenceType())
143 return kReferencePtrToGCManaged
;
145 return kRawPtrToGCManaged
;
148 return kRefPtrToGCManaged
;
150 return kOwnPtrToGCManaged
;
151 assert(false && "Unknown smart pointer kind");