Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / tools / clang / blink_gc_plugin / RecordInfo.h
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.
4
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.
8
9 #ifndef TOOLS_BLINK_GC_PLUGIN_RECORD_INFO_H_
10 #define TOOLS_BLINK_GC_PLUGIN_RECORD_INFO_H_
11
12 #include <map>
13 #include <vector>
14
15 #include "Edge.h"
16
17 #include "clang/AST/AST.h"
18 #include "clang/AST/CXXInheritance.h"
19
20 class RecordCache;
21
22 // A potentially tracable and/or lifetime affecting point in the object graph.
23 class GraphPoint {
24  public:
25   GraphPoint() : traced_(false) {}
26   void MarkTraced() { traced_ = true; }
27   bool IsProperlyTraced() { return traced_ || !NeedsTracing().IsNeeded(); }
28   virtual const TracingStatus NeedsTracing() = 0;
29
30  private:
31   bool traced_;
32 };
33
34 class BasePoint : public GraphPoint {
35  public:
36   BasePoint(const clang::CXXBaseSpecifier& spec,
37             RecordInfo* info,
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_; }
43
44  private:
45   const clang::CXXBaseSpecifier& spec_;
46   RecordInfo* info_;
47   TracingStatus status_;
48 };
49
50 class FieldPoint : public GraphPoint {
51  public:
52   FieldPoint(clang::FieldDecl* field, Edge* edge)
53       : field_(field), edge_(edge) {}
54   const TracingStatus NeedsTracing() {
55     return edge_->NeedsTracing(Edge::kRecursive);
56   }
57   clang::FieldDecl* field() { return field_; }
58   Edge* edge() { return edge_; }
59
60  private:
61   clang::FieldDecl* field_;
62   Edge* edge_;
63
64   friend class RecordCache;
65   void deleteEdge() { delete edge_; }
66 };
67
68 // Wrapper class to lazily collect information about a C++ record.
69 class RecordInfo {
70  public:
71   typedef std::map<clang::CXXRecordDecl*, BasePoint> Bases;
72   typedef std::map<clang::FieldDecl*, FieldPoint> Fields;
73   typedef std::vector<const clang::Type*> TemplateArgs;
74
75   ~RecordInfo();
76
77   clang::CXXRecordDecl* record() const { return record_; }
78   const std::string& name() const { return name_; }
79   Fields& GetFields();
80   Bases& GetBases();
81   clang::CXXMethodDecl* GetTraceMethod();
82   clang::CXXMethodDecl* GetTraceDispatchMethod();
83   clang::CXXMethodDecl* GetFinalizeDispatchMethod();
84
85   bool GetTemplateArgs(size_t count, TemplateArgs* output_args);
86
87   bool IsHeapAllocatedCollection();
88   bool IsGCDerived();
89   bool IsGCAllocated();
90   bool IsGCFinalized();
91   bool IsGCMixin();
92   bool IsStackAllocated();
93   bool IsNonNewable();
94   bool IsOnlyPlacementNewable();
95   clang::CXXMethodDecl* DeclaresNewOperator();
96
97   bool RequiresTraceMethod();
98   bool NeedsFinalization();
99   TracingStatus NeedsTracing(Edge::NeedsTracingOption);
100   clang::CXXMethodDecl* InheritsNonVirtualTrace();
101   bool IsConsideredAbstract();
102
103  private:
104   RecordInfo(clang::CXXRecordDecl* record, RecordCache* cache);
105
106   Fields* CollectFields();
107   Bases* CollectBases();
108   void DetermineTracingMethods();
109   bool InheritsTrace();
110
111   Edge* CreateEdge(const clang::Type* type);
112
113   RecordCache* cache_;
114   clang::CXXRecordDecl* record_;
115   const std::string name_;
116   TracingStatus fields_need_tracing_;
117   Bases* bases_;
118   Fields* fields_;
119
120   enum CachedBool { kFalse = 0, kTrue = 1, kNotComputed = 2 };
121   CachedBool is_stack_allocated_;
122   CachedBool is_non_newable_;
123   CachedBool is_only_placement_newable_;
124   CachedBool does_need_finalization_;
125
126   bool determined_trace_methods_;
127   clang::CXXMethodDecl* trace_method_;
128   clang::CXXMethodDecl* trace_dispatch_method_;
129   clang::CXXMethodDecl* finalize_dispatch_method_;
130
131   bool is_gc_derived_;
132   clang::CXXBasePaths* base_paths_;
133
134   friend class RecordCache;
135 };
136
137 class RecordCache {
138  public:
139   RecordInfo* Lookup(clang::CXXRecordDecl* record);
140
141   RecordInfo* Lookup(const clang::CXXRecordDecl* record) {
142     return Lookup(const_cast<clang::CXXRecordDecl*>(record));
143   }
144
145   RecordInfo* Lookup(clang::DeclContext* decl) {
146     return Lookup(clang::dyn_cast<clang::CXXRecordDecl>(decl));
147   }
148
149   RecordInfo* Lookup(const clang::Type* type) {
150     return Lookup(type->getAsCXXRecordDecl());
151   }
152
153   RecordInfo* Lookup(const clang::QualType& type) {
154     return Lookup(type.getTypePtr());
155   }
156
157   ~RecordCache() {
158     for (Cache::iterator it = cache_.begin(); it != cache_.end(); ++it) {
159       if (!it->second.fields_)
160         continue;
161       for (RecordInfo::Fields::iterator fit = it->second.fields_->begin();
162         fit != it->second.fields_->end();
163         ++fit) {
164         fit->second.deleteEdge();
165       }
166     }
167   }
168
169  private:
170   typedef std::map<clang::CXXRecordDecl*, RecordInfo> Cache;
171   Cache cache_;
172 };
173
174 #endif  // TOOLS_BLINK_GC_PLUGIN_RECORD_INFO_H_