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 void MarkTraced() { traced_
= true; }
27 bool IsProperlyTraced() { return traced_
|| !NeedsTracing().IsNeeded(); }
28 virtual const TracingStatus
NeedsTracing() = 0;
34 class BasePoint
: public GraphPoint
{
36 BasePoint(const clang::CXXBaseSpecifier
& spec
,
38 const TracingStatus
& status
)
39 : spec_(spec
), info_(info
), status_(status
) {}
40 const TracingStatus
NeedsTracing() { return status_
; }
41 const clang::CXXBaseSpecifier
& spec() { return spec_
; }
42 RecordInfo
* info() { return info_
; }
45 const clang::CXXBaseSpecifier
& spec_
;
47 TracingStatus status_
;
50 class FieldPoint
: public GraphPoint
{
52 FieldPoint(clang::FieldDecl
* field
, Edge
* edge
)
53 : field_(field
), edge_(edge
) {}
54 const TracingStatus
NeedsTracing() {
55 return edge_
->NeedsTracing(Edge::kRecursive
);
57 clang::FieldDecl
* field() { return field_
; }
58 Edge
* edge() { return edge_
; }
61 clang::FieldDecl
* field_
;
64 friend class RecordCache
;
65 void deleteEdge() { delete edge_
; }
68 // Wrapper class to lazily collect information about a C++ record.
71 typedef std::map
<clang::CXXRecordDecl
*, BasePoint
> Bases
;
72 typedef std::map
<clang::FieldDecl
*, FieldPoint
> Fields
;
73 typedef std::vector
<const clang::Type
*> TemplateArgs
;
77 clang::CXXRecordDecl
* record() const { return record_
; }
78 const std::string
& name() const { return name_
; }
81 clang::CXXMethodDecl
* GetTraceMethod();
82 clang::CXXMethodDecl
* GetTraceDispatchMethod();
83 clang::CXXMethodDecl
* GetFinalizeDispatchMethod();
85 bool GetTemplateArgs(size_t count
, TemplateArgs
* output_args
);
87 bool IsHeapAllocatedCollection();
92 bool IsStackAllocated();
94 bool IsOnlyPlacementNewable();
95 bool IsGCMixinInstance();
96 clang::CXXMethodDecl
* DeclaresNewOperator();
98 bool RequiresTraceMethod();
99 bool NeedsFinalization();
100 bool DeclaresGCMixinMethods();
101 bool DeclaresLocalTraceMethod();
102 TracingStatus
NeedsTracing(Edge::NeedsTracingOption
);
103 clang::CXXMethodDecl
* InheritsNonVirtualTrace();
104 bool IsConsideredAbstract();
106 static clang::CXXRecordDecl
* GetDependentTemplatedDecl(const clang::Type
&);
109 RecordInfo(clang::CXXRecordDecl
* record
, RecordCache
* cache
);
113 Fields
* CollectFields();
114 Bases
* CollectBases();
115 void DetermineTracingMethods();
116 bool InheritsTrace();
118 Edge
* CreateEdge(const clang::Type
* type
);
121 clang::CXXRecordDecl
* record_
;
122 const std::string name_
;
123 TracingStatus fields_need_tracing_
;
127 enum CachedBool
{ kFalse
= 0, kTrue
= 1, kNotComputed
= 2 };
128 CachedBool is_stack_allocated_
;
129 CachedBool is_non_newable_
;
130 CachedBool is_only_placement_newable_
;
131 CachedBool does_need_finalization_
;
132 CachedBool has_gc_mixin_methods_
;
133 CachedBool is_declaring_local_trace_
;
135 bool determined_trace_methods_
;
136 clang::CXXMethodDecl
* trace_method_
;
137 clang::CXXMethodDecl
* trace_dispatch_method_
;
138 clang::CXXMethodDecl
* finalize_dispatch_method_
;
142 std::vector
<std::string
> gc_base_names_
;
144 friend class RecordCache
;
149 RecordInfo
* Lookup(clang::CXXRecordDecl
* record
);
151 RecordInfo
* Lookup(const clang::CXXRecordDecl
* record
) {
152 return Lookup(const_cast<clang::CXXRecordDecl
*>(record
));
155 RecordInfo
* Lookup(clang::DeclContext
* decl
) {
156 return Lookup(clang::dyn_cast
<clang::CXXRecordDecl
>(decl
));
159 RecordInfo
* Lookup(const clang::Type
* type
) {
160 return Lookup(type
->getAsCXXRecordDecl());
163 RecordInfo
* Lookup(const clang::QualType
& type
) {
164 return Lookup(type
.getTypePtr());
168 for (Cache::iterator it
= cache_
.begin(); it
!= cache_
.end(); ++it
) {
169 if (!it
->second
.fields_
)
171 for (RecordInfo::Fields::iterator fit
= it
->second
.fields_
->begin();
172 fit
!= it
->second
.fields_
->end();
174 fit
->second
.deleteEdge();
180 typedef std::map
<clang::CXXRecordDecl
*, RecordInfo
> Cache
;
184 #endif // TOOLS_BLINK_GC_PLUGIN_RECORD_INFO_H_