summaryrefslogtreecommitdiffstats
path: root/chromium/tools/clang/blink_gc_plugin/RecordInfo.h
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/tools/clang/blink_gc_plugin/RecordInfo.h')
-rw-r--r--chromium/tools/clang/blink_gc_plugin/RecordInfo.h173
1 files changed, 173 insertions, 0 deletions
diff --git a/chromium/tools/clang/blink_gc_plugin/RecordInfo.h b/chromium/tools/clang/blink_gc_plugin/RecordInfo.h
new file mode 100644
index 00000000000..a2fa10e7a7a
--- /dev/null
+++ b/chromium/tools/clang/blink_gc_plugin/RecordInfo.h
@@ -0,0 +1,173 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file provides a wrapper for CXXRecordDecl that accumulates GC related
+// information about a class. Accumulated information is memoized and the info
+// objects are stored in a RecordCache.
+
+#ifndef TOOLS_BLINK_GC_PLUGIN_RECORD_INFO_H_
+#define TOOLS_BLINK_GC_PLUGIN_RECORD_INFO_H_
+
+#include <map>
+#include <vector>
+
+#include "Edge.h"
+
+#include "clang/AST/AST.h"
+#include "clang/AST/CXXInheritance.h"
+
+class RecordCache;
+
+// A potentially tracable and/or lifetime affecting point in the object graph.
+class GraphPoint {
+ public:
+ GraphPoint() : traced_(false) {}
+ void MarkTraced() { traced_ = true; }
+ bool IsProperlyTraced() { return traced_ || !NeedsTracing().IsNeeded(); }
+ virtual const TracingStatus NeedsTracing() = 0;
+
+ private:
+ bool traced_;
+};
+
+class BasePoint : public GraphPoint {
+ public:
+ BasePoint(const clang::CXXBaseSpecifier& spec,
+ RecordInfo* info,
+ const TracingStatus& status)
+ : spec_(spec), info_(info), status_(status) {}
+ const TracingStatus NeedsTracing() { return status_; }
+ const clang::CXXBaseSpecifier& spec() { return spec_; }
+ RecordInfo* info() { return info_; }
+
+ private:
+ const clang::CXXBaseSpecifier& spec_;
+ RecordInfo* info_;
+ TracingStatus status_;
+};
+
+class FieldPoint : public GraphPoint {
+ public:
+ FieldPoint(clang::FieldDecl* field, Edge* edge)
+ : field_(field), edge_(edge) {}
+ const TracingStatus NeedsTracing() {
+ return edge_->NeedsTracing(Edge::kRecursive);
+ }
+ clang::FieldDecl* field() { return field_; }
+ Edge* edge() { return edge_; }
+
+ private:
+ clang::FieldDecl* field_;
+ Edge* edge_;
+
+ friend class RecordCache;
+ void deleteEdge() { delete edge_; }
+};
+
+// Wrapper class to lazily collect information about a C++ record.
+class RecordInfo {
+ public:
+ typedef std::map<clang::CXXRecordDecl*, BasePoint> Bases;
+ typedef std::map<clang::FieldDecl*, FieldPoint> Fields;
+ typedef std::vector<const clang::Type*> TemplateArgs;
+
+ ~RecordInfo();
+
+ clang::CXXRecordDecl* record() const { return record_; }
+ const std::string& name() const { return name_; }
+ Fields& GetFields();
+ Bases& GetBases();
+ clang::CXXMethodDecl* GetTraceMethod();
+ clang::CXXMethodDecl* GetTraceDispatchMethod();
+ clang::CXXMethodDecl* GetFinalizeDispatchMethod();
+
+ bool GetTemplateArgs(size_t count, TemplateArgs* output_args);
+
+ bool IsHeapAllocatedCollection();
+ bool IsGCDerived();
+ bool IsGCAllocated();
+ bool IsGCFinalized();
+ bool IsGCMixin();
+ bool IsStackAllocated();
+ bool IsNonNewable();
+ bool IsOnlyPlacementNewable();
+ clang::CXXMethodDecl* DeclaresNewOperator();
+
+ bool RequiresTraceMethod();
+ bool NeedsFinalization();
+ TracingStatus NeedsTracing(Edge::NeedsTracingOption);
+ clang::CXXMethodDecl* InheritsNonVirtualTrace();
+ bool IsConsideredAbstract();
+
+ private:
+ RecordInfo(clang::CXXRecordDecl* record, RecordCache* cache);
+
+ Fields* CollectFields();
+ Bases* CollectBases();
+ void DetermineTracingMethods();
+ bool InheritsTrace();
+
+ Edge* CreateEdge(const clang::Type* type);
+
+ RecordCache* cache_;
+ clang::CXXRecordDecl* record_;
+ const std::string name_;
+ TracingStatus fields_need_tracing_;
+ Bases* bases_;
+ Fields* fields_;
+
+ enum CachedBool { kFalse = 0, kTrue = 1, kNotComputed = 2 };
+ CachedBool is_stack_allocated_;
+ CachedBool is_non_newable_;
+ CachedBool is_only_placement_newable_;
+
+ bool determined_trace_methods_;
+ clang::CXXMethodDecl* trace_method_;
+ clang::CXXMethodDecl* trace_dispatch_method_;
+ clang::CXXMethodDecl* finalize_dispatch_method_;
+
+ bool is_gc_derived_;
+ clang::CXXBasePaths* base_paths_;
+
+ friend class RecordCache;
+};
+
+class RecordCache {
+ public:
+ RecordInfo* Lookup(clang::CXXRecordDecl* record);
+
+ RecordInfo* Lookup(const clang::CXXRecordDecl* record) {
+ return Lookup(const_cast<clang::CXXRecordDecl*>(record));
+ }
+
+ RecordInfo* Lookup(clang::DeclContext* decl) {
+ return Lookup(clang::dyn_cast<clang::CXXRecordDecl>(decl));
+ }
+
+ RecordInfo* Lookup(const clang::Type* type) {
+ return Lookup(type->getAsCXXRecordDecl());
+ }
+
+ RecordInfo* Lookup(const clang::QualType& type) {
+ return Lookup(type.getTypePtr());
+ }
+
+ ~RecordCache() {
+ for (Cache::iterator it = cache_.begin(); it != cache_.end(); ++it) {
+ if (!it->second.fields_)
+ continue;
+ for (RecordInfo::Fields::iterator fit = it->second.fields_->begin();
+ fit != it->second.fields_->end();
+ ++fit) {
+ fit->second.deleteEdge();
+ }
+ }
+ }
+
+ private:
+ typedef std::map<clang::CXXRecordDecl*, RecordInfo> Cache;
+ Cache cache_;
+};
+
+#endif // TOOLS_BLINK_GC_PLUGIN_RECORD_INFO_H_