1 // Copyright 2014 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 // This file provides a wrapper for CXXRecordDecl that accumulates GC related
6 // information about a class. Accumulated information is memoized and the info
7 // objects are stored in a RecordCache.
9 #ifndef TOOLS_BLINK_GC_PLUGIN_RECORD_INFO_H_
10 #define TOOLS_BLINK_GC_PLUGIN_RECORD_INFO_H_
17 #include "clang/AST/AST.h"
18 #include "clang/AST/CXXInheritance.h"
22 // A potentially tracable and/or lifetime affecting point in the object graph.
25 GraphPoint() : traced_(false) {}
26 virtual ~GraphPoint() {}
27 void MarkTraced() { traced_
= true; }
28 bool IsProperlyTraced() { return traced_
|| !NeedsTracing().IsNeeded(); }
29 virtual const TracingStatus
NeedsTracing() = 0;
35 class BasePoint
: public GraphPoint
{
37 BasePoint(const clang::CXXBaseSpecifier
& spec
,
39 const TracingStatus
& status
)
40 : spec_(spec
), info_(info
), status_(status
) {}
41 const TracingStatus
NeedsTracing() { return status_
; }
42 const clang::CXXBaseSpecifier
& spec() { return spec_
; }
43 RecordInfo
* info() { return info_
; }
46 const clang::CXXBaseSpecifier
& spec_
;
48 TracingStatus status_
;
51 class FieldPoint
: public GraphPoint
{
53 FieldPoint(clang::FieldDecl
* field
, Edge
* edge
)
54 : field_(field
), edge_(edge
) {}
55 const TracingStatus
NeedsTracing() {
56 return edge_
->NeedsTracing(Edge::kRecursive
);
58 clang::FieldDecl
* field() { return field_
; }
59 Edge
* edge() { return edge_
; }
62 clang::FieldDecl
* field_
;
65 friend class RecordCache
;
66 void deleteEdge() { delete edge_
; }
69 // Wrapper class to lazily collect information about a C++ record.
72 typedef std::map
<clang::CXXRecordDecl
*, BasePoint
> Bases
;
73 typedef std::map
<clang::FieldDecl
*, FieldPoint
> Fields
;
74 typedef std::vector
<const clang::Type
*> TemplateArgs
;
78 clang::CXXRecordDecl
* record() const { return record_
; }
79 const std::string
& name() const { return name_
; }
82 clang::CXXMethodDecl
* GetTraceMethod();
83 clang::CXXMethodDecl
* GetTraceDispatchMethod();
84 clang::CXXMethodDecl
* GetFinalizeDispatchMethod();
86 bool GetTemplateArgs(size_t count
, TemplateArgs
* output_args
);
88 bool IsHeapAllocatedCollection();
93 bool IsStackAllocated();
95 bool IsOnlyPlacementNewable();
96 bool IsGCMixinInstance();
97 bool IsEagerlyFinalized();
101 clang::CXXMethodDecl
* DeclaresNewOperator();
103 bool RequiresTraceMethod();
104 bool NeedsFinalization();
105 bool DeclaresGCMixinMethods();
106 bool DeclaresLocalTraceMethod();
107 TracingStatus
NeedsTracing(Edge::NeedsTracingOption
);
108 clang::CXXMethodDecl
* InheritsNonVirtualTrace();
109 bool IsConsideredAbstract();
111 static clang::CXXRecordDecl
* GetDependentTemplatedDecl(const clang::Type
&);
114 RecordInfo(clang::CXXRecordDecl
* record
, RecordCache
* cache
);
118 Fields
* CollectFields();
119 Bases
* CollectBases();
120 void DetermineTracingMethods();
121 bool InheritsTrace();
123 Edge
* CreateEdge(const clang::Type
* type
);
126 clang::CXXRecordDecl
* record_
;
127 const std::string name_
;
128 TracingStatus fields_need_tracing_
;
132 enum CachedBool
{ kFalse
= 0, kTrue
= 1, kNotComputed
= 2 };
133 CachedBool is_stack_allocated_
;
134 CachedBool is_non_newable_
;
135 CachedBool is_only_placement_newable_
;
136 CachedBool does_need_finalization_
;
137 CachedBool has_gc_mixin_methods_
;
138 CachedBool is_declaring_local_trace_
;
139 CachedBool is_eagerly_finalized_
;
141 bool determined_trace_methods_
;
142 clang::CXXMethodDecl
* trace_method_
;
143 clang::CXXMethodDecl
* trace_dispatch_method_
;
144 clang::CXXMethodDecl
* finalize_dispatch_method_
;
148 std::vector
<std::string
> gc_base_names_
;
150 friend class RecordCache
;
155 RecordInfo
* Lookup(clang::CXXRecordDecl
* record
);
157 RecordInfo
* Lookup(const clang::CXXRecordDecl
* record
) {
158 return Lookup(const_cast<clang::CXXRecordDecl
*>(record
));
161 RecordInfo
* Lookup(clang::DeclContext
* decl
) {
162 return Lookup(clang::dyn_cast
<clang::CXXRecordDecl
>(decl
));
165 RecordInfo
* Lookup(const clang::Type
* type
) {
166 return Lookup(type
->getAsCXXRecordDecl());
169 RecordInfo
* Lookup(const clang::QualType
& type
) {
170 return Lookup(type
.getTypePtr());
174 for (Cache::iterator it
= cache_
.begin(); it
!= cache_
.end(); ++it
) {
175 if (!it
->second
.fields_
)
177 for (RecordInfo::Fields::iterator fit
= it
->second
.fields_
->begin();
178 fit
!= it
->second
.fields_
->end();
180 fit
->second
.deleteEdge();
186 typedef std::map
<clang::CXXRecordDecl
*, RecordInfo
> Cache
;
190 #endif // TOOLS_BLINK_GC_PLUGIN_RECORD_INFO_H_