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 clang::CXXMethodDecl
* DeclaresNewOperator();
99 bool RequiresTraceMethod();
100 bool NeedsFinalization();
101 bool DeclaresGCMixinMethods();
102 bool DeclaresLocalTraceMethod();
103 TracingStatus
NeedsTracing(Edge::NeedsTracingOption
);
104 clang::CXXMethodDecl
* InheritsNonVirtualTrace();
105 bool IsConsideredAbstract();
107 static clang::CXXRecordDecl
* GetDependentTemplatedDecl(const clang::Type
&);
110 RecordInfo(clang::CXXRecordDecl
* record
, RecordCache
* cache
);
114 Fields
* CollectFields();
115 Bases
* CollectBases();
116 void DetermineTracingMethods();
117 bool InheritsTrace();
119 Edge
* CreateEdge(const clang::Type
* type
);
122 clang::CXXRecordDecl
* record_
;
123 const std::string name_
;
124 TracingStatus fields_need_tracing_
;
128 enum CachedBool
{ kFalse
= 0, kTrue
= 1, kNotComputed
= 2 };
129 CachedBool is_stack_allocated_
;
130 CachedBool is_non_newable_
;
131 CachedBool is_only_placement_newable_
;
132 CachedBool does_need_finalization_
;
133 CachedBool has_gc_mixin_methods_
;
134 CachedBool is_declaring_local_trace_
;
136 bool determined_trace_methods_
;
137 clang::CXXMethodDecl
* trace_method_
;
138 clang::CXXMethodDecl
* trace_dispatch_method_
;
139 clang::CXXMethodDecl
* finalize_dispatch_method_
;
143 std::vector
<std::string
> gc_base_names_
;
145 friend class RecordCache
;
150 RecordInfo
* Lookup(clang::CXXRecordDecl
* record
);
152 RecordInfo
* Lookup(const clang::CXXRecordDecl
* record
) {
153 return Lookup(const_cast<clang::CXXRecordDecl
*>(record
));
156 RecordInfo
* Lookup(clang::DeclContext
* decl
) {
157 return Lookup(clang::dyn_cast
<clang::CXXRecordDecl
>(decl
));
160 RecordInfo
* Lookup(const clang::Type
* type
) {
161 return Lookup(type
->getAsCXXRecordDecl());
164 RecordInfo
* Lookup(const clang::QualType
& type
) {
165 return Lookup(type
.getTypePtr());
169 for (Cache::iterator it
= cache_
.begin(); it
!= cache_
.end(); ++it
) {
170 if (!it
->second
.fields_
)
172 for (RecordInfo::Fields::iterator fit
= it
->second
.fields_
->begin();
173 fit
!= it
->second
.fields_
->end();
175 fit
->second
.deleteEdge();
181 typedef std::map
<clang::CXXRecordDecl
*, RecordInfo
> Cache
;
185 #endif // TOOLS_BLINK_GC_PLUGIN_RECORD_INFO_H_