| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // This clang plugin checks various invariants of the Blink garbage | 5 // This clang plugin checks various invariants of the Blink garbage |
| 6 // collection infrastructure. | 6 // collection infrastructure. |
| 7 // | 7 // |
| 8 // Errors are described at: | 8 // Errors are described at: |
| 9 // http://www.chromium.org/developers/blink-gc-plugin-errors | 9 // http://www.chromium.org/developers/blink-gc-plugin-errors |
| 10 | 10 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 | 61 |
| 62 const char kFinalizerAccessesEagerlyFinalizedField[] = | 62 const char kFinalizerAccessesEagerlyFinalizedField[] = |
| 63 "[blink-gc] Finalizer %0 accesses eagerly finalized field %1."; | 63 "[blink-gc] Finalizer %0 accesses eagerly finalized field %1."; |
| 64 | 64 |
| 65 const char kRawPtrToGCManagedClassNote[] = | 65 const char kRawPtrToGCManagedClassNote[] = |
| 66 "[blink-gc] Raw pointer field %0 to a GC managed class declared here:"; | 66 "[blink-gc] Raw pointer field %0 to a GC managed class declared here:"; |
| 67 | 67 |
| 68 const char kRefPtrToGCManagedClassNote[] = | 68 const char kRefPtrToGCManagedClassNote[] = |
| 69 "[blink-gc] RefPtr field %0 to a GC managed class declared here:"; | 69 "[blink-gc] RefPtr field %0 to a GC managed class declared here:"; |
| 70 | 70 |
| 71 const char kReferencePtrToGCManagedClassNote[] = | |
| 72 "[blink-gc] Reference pointer field %0 to a GC managed class" | |
| 73 " declared here:"; | |
| 74 | |
| 75 const char kOwnPtrToGCManagedClassNote[] = | 71 const char kOwnPtrToGCManagedClassNote[] = |
| 76 "[blink-gc] OwnPtr field %0 to a GC managed class declared here:"; | 72 "[blink-gc] OwnPtr field %0 to a GC managed class declared here:"; |
| 77 | 73 |
| 78 const char kMemberToGCUnmanagedClassNote[] = | 74 const char kMemberToGCUnmanagedClassNote[] = |
| 79 "[blink-gc] Member field %0 to non-GC managed class declared here:"; | 75 "[blink-gc] Member field %0 to non-GC managed class declared here:"; |
| 80 | 76 |
| 81 const char kStackAllocatedFieldNote[] = | 77 const char kStackAllocatedFieldNote[] = |
| 82 "[blink-gc] Stack-allocated field %0 declared here:"; | 78 "[blink-gc] Stack-allocated field %0 declared here:"; |
| 83 | 79 |
| 84 const char kMemberInUnmanagedClassNote[] = | 80 const char kMemberInUnmanagedClassNote[] = |
| (...skipping 765 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 850 // - Part objects must not be GC derived types. | 846 // - Part objects must not be GC derived types. |
| 851 // - An on-heap class must never contain GC roots. | 847 // - An on-heap class must never contain GC roots. |
| 852 // - Only stack-allocated types may point to stack-allocated types. | 848 // - Only stack-allocated types may point to stack-allocated types. |
| 853 class CheckFieldsVisitor : public RecursiveEdgeVisitor { | 849 class CheckFieldsVisitor : public RecursiveEdgeVisitor { |
| 854 public: | 850 public: |
| 855 | 851 |
| 856 enum Error { | 852 enum Error { |
| 857 kRawPtrToGCManaged, | 853 kRawPtrToGCManaged, |
| 858 kRawPtrToGCManagedWarning, | 854 kRawPtrToGCManagedWarning, |
| 859 kRefPtrToGCManaged, | 855 kRefPtrToGCManaged, |
| 860 kReferencePtrToGCManaged, | |
| 861 kReferencePtrToGCManagedWarning, | |
| 862 kOwnPtrToGCManaged, | 856 kOwnPtrToGCManaged, |
| 863 kMemberToGCUnmanaged, | 857 kMemberToGCUnmanaged, |
| 864 kMemberInUnmanaged, | 858 kMemberInUnmanaged, |
| 865 kPtrFromHeapToStack, | 859 kPtrFromHeapToStack, |
| 866 kGCDerivedPartObject | 860 kGCDerivedPartObject |
| 867 }; | 861 }; |
| 868 | 862 |
| 869 typedef std::vector<std::pair<FieldPoint*, Error> > Errors; | 863 typedef std::vector<std::pair<FieldPoint*, Error> > Errors; |
| 870 | 864 |
| 871 CheckFieldsVisitor(const BlinkGCPluginOptions& options) | 865 CheckFieldsVisitor(const BlinkGCPluginOptions& options) |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 943 // also disallow T* in stack-allocated types. | 937 // also disallow T* in stack-allocated types. |
| 944 if (options_.enable_oilpan) { | 938 if (options_.enable_oilpan) { |
| 945 if (Parent()->IsOwnPtr() || | 939 if (Parent()->IsOwnPtr() || |
| 946 Parent()->IsRawPtrClass() || | 940 Parent()->IsRawPtrClass() || |
| 947 (stack_allocated_host_ && Parent()->IsRawPtr())) { | 941 (stack_allocated_host_ && Parent()->IsRawPtr())) { |
| 948 invalid_fields_.push_back(std::make_pair( | 942 invalid_fields_.push_back(std::make_pair( |
| 949 current_, InvalidSmartPtr(Parent()))); | 943 current_, InvalidSmartPtr(Parent()))); |
| 950 return; | 944 return; |
| 951 } | 945 } |
| 952 if (options_.warn_raw_ptr && Parent()->IsRawPtr()) { | 946 if (options_.warn_raw_ptr && Parent()->IsRawPtr()) { |
| 953 if (static_cast<RawPtr*>(Parent())->HasReferenceType()) { | 947 invalid_fields_.push_back(std::make_pair( |
| 954 invalid_fields_.push_back(std::make_pair( | 948 current_, kRawPtrToGCManagedWarning)); |
| 955 current_, kReferencePtrToGCManagedWarning)); | |
| 956 } else { | |
| 957 invalid_fields_.push_back(std::make_pair( | |
| 958 current_, kRawPtrToGCManagedWarning)); | |
| 959 } | |
| 960 } | 949 } |
| 961 return; | 950 return; |
| 962 } | 951 } |
| 963 | 952 |
| 964 if (Parent()->IsRawPtr() || Parent()->IsRefPtr() || Parent()->IsOwnPtr()) { | 953 if (Parent()->IsRawPtr() || Parent()->IsRefPtr() || Parent()->IsOwnPtr()) { |
| 965 invalid_fields_.push_back(std::make_pair( | 954 invalid_fields_.push_back(std::make_pair( |
| 966 current_, InvalidSmartPtr(Parent()))); | 955 current_, InvalidSmartPtr(Parent()))); |
| 967 return; | 956 return; |
| 968 } | 957 } |
| 969 } | 958 } |
| 970 | 959 |
| 971 void AtCollection(Collection* edge) override { | 960 void AtCollection(Collection* edge) override { |
| 972 if (edge->on_heap() && Parent() && Parent()->IsOwnPtr()) | 961 if (edge->on_heap() && Parent() && Parent()->IsOwnPtr()) |
| 973 invalid_fields_.push_back(std::make_pair(current_, kOwnPtrToGCManaged)); | 962 invalid_fields_.push_back(std::make_pair(current_, kOwnPtrToGCManaged)); |
| 974 } | 963 } |
| 975 | 964 |
| 976 static bool IsWarning(Error error) { | |
| 977 if (error == kRawPtrToGCManagedWarning) | |
| 978 return true; | |
| 979 if (error == kReferencePtrToGCManagedWarning) | |
| 980 return true; | |
| 981 return false; | |
| 982 } | |
| 983 | |
| 984 static bool IsRawPtrError(Error error) { | |
| 985 return error == kRawPtrToGCManaged || | |
| 986 error == kRawPtrToGCManagedWarning; | |
| 987 } | |
| 988 | |
| 989 static bool IsReferencePtrError(Error error) { | |
| 990 return error == kReferencePtrToGCManaged || | |
| 991 error == kReferencePtrToGCManagedWarning; | |
| 992 } | |
| 993 | |
| 994 private: | 965 private: |
| 995 Error InvalidSmartPtr(Edge* ptr) { | 966 Error InvalidSmartPtr(Edge* ptr) { |
| 996 if (ptr->IsRawPtr()) { | 967 if (ptr->IsRawPtr()) |
| 997 if (static_cast<RawPtr*>(ptr)->HasReferenceType()) | 968 return kRawPtrToGCManaged; |
| 998 return kReferencePtrToGCManaged; | |
| 999 else | |
| 1000 return kRawPtrToGCManaged; | |
| 1001 } | |
| 1002 if (ptr->IsRefPtr()) | 969 if (ptr->IsRefPtr()) |
| 1003 return kRefPtrToGCManaged; | 970 return kRefPtrToGCManaged; |
| 1004 if (ptr->IsOwnPtr()) | 971 if (ptr->IsOwnPtr()) |
| 1005 return kOwnPtrToGCManaged; | 972 return kOwnPtrToGCManaged; |
| 1006 assert(false && "Unknown smart pointer kind"); | 973 assert(false && "Unknown smart pointer kind"); |
| 1007 } | 974 } |
| 1008 | 975 |
| 1009 const BlinkGCPluginOptions& options_; | 976 const BlinkGCPluginOptions& options_; |
| 1010 FieldPoint* current_; | 977 FieldPoint* current_; |
| 1011 bool stack_allocated_host_; | 978 bool stack_allocated_host_; |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1103 | 1070 |
| 1104 // Register note messages. | 1071 // Register note messages. |
| 1105 diag_base_requires_tracing_note_ = diagnostic_.getCustomDiagID( | 1072 diag_base_requires_tracing_note_ = diagnostic_.getCustomDiagID( |
| 1106 DiagnosticsEngine::Note, kBaseRequiresTracingNote); | 1073 DiagnosticsEngine::Note, kBaseRequiresTracingNote); |
| 1107 diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID( | 1074 diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID( |
| 1108 DiagnosticsEngine::Note, kFieldRequiresTracingNote); | 1075 DiagnosticsEngine::Note, kFieldRequiresTracingNote); |
| 1109 diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 1076 diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
| 1110 DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote); | 1077 DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote); |
| 1111 diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 1078 diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
| 1112 DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote); | 1079 DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote); |
| 1113 diag_reference_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | |
| 1114 DiagnosticsEngine::Note, kReferencePtrToGCManagedClassNote); | |
| 1115 diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 1080 diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
| 1116 DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote); | 1081 DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote); |
| 1117 diag_member_to_gc_unmanaged_class_note_ = diagnostic_.getCustomDiagID( | 1082 diag_member_to_gc_unmanaged_class_note_ = diagnostic_.getCustomDiagID( |
| 1118 DiagnosticsEngine::Note, kMemberToGCUnmanagedClassNote); | 1083 DiagnosticsEngine::Note, kMemberToGCUnmanagedClassNote); |
| 1119 diag_stack_allocated_field_note_ = diagnostic_.getCustomDiagID( | 1084 diag_stack_allocated_field_note_ = diagnostic_.getCustomDiagID( |
| 1120 DiagnosticsEngine::Note, kStackAllocatedFieldNote); | 1085 DiagnosticsEngine::Note, kStackAllocatedFieldNote); |
| 1121 diag_member_in_unmanaged_class_note_ = diagnostic_.getCustomDiagID( | 1086 diag_member_in_unmanaged_class_note_ = diagnostic_.getCustomDiagID( |
| 1122 DiagnosticsEngine::Note, kMemberInUnmanagedClassNote); | 1087 DiagnosticsEngine::Note, kMemberInUnmanagedClassNote); |
| 1123 diag_part_object_to_gc_derived_class_note_ = diagnostic_.getCustomDiagID( | 1088 diag_part_object_to_gc_derived_class_note_ = diagnostic_.getCustomDiagID( |
| 1124 DiagnosticsEngine::Note, kPartObjectToGCDerivedClassNote); | 1089 DiagnosticsEngine::Note, kPartObjectToGCDerivedClassNote); |
| (...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1655 const Edge::LivenessKind& kind, | 1620 const Edge::LivenessKind& kind, |
| 1656 const string& loc) { | 1621 const string& loc) { |
| 1657 json_->OpenObject(); | 1622 json_->OpenObject(); |
| 1658 json_->Write("src", src->record()->getQualifiedNameAsString()); | 1623 json_->Write("src", src->record()->getQualifiedNameAsString()); |
| 1659 json_->Write("dst", dst->record()->getQualifiedNameAsString()); | 1624 json_->Write("dst", dst->record()->getQualifiedNameAsString()); |
| 1660 json_->Write("lbl", lbl); | 1625 json_->Write("lbl", lbl); |
| 1661 json_->Write("kind", kind); | 1626 json_->Write("kind", kind); |
| 1662 json_->Write("loc", loc); | 1627 json_->Write("loc", loc); |
| 1663 json_->Write("ptr", | 1628 json_->Write("ptr", |
| 1664 !Parent() ? "val" : | 1629 !Parent() ? "val" : |
| 1665 Parent()->IsRawPtr() ? | 1630 Parent()->IsRawPtr() ? "raw" : |
| 1666 (static_cast<RawPtr*>(Parent())->HasReferenceType() ? | |
| 1667 "reference" : "raw") : | |
| 1668 Parent()->IsRefPtr() ? "ref" : | 1631 Parent()->IsRefPtr() ? "ref" : |
| 1669 Parent()->IsOwnPtr() ? "own" : | 1632 Parent()->IsOwnPtr() ? "own" : |
| 1670 (Parent()->IsMember() || | 1633 (Parent()->IsMember() || |
| 1671 Parent()->IsWeakMember()) ? "mem" : | 1634 Parent()->IsWeakMember()) ? "mem" : |
| 1672 "val"); | 1635 "val"); |
| 1673 json_->CloseObject(); | 1636 json_->CloseObject(); |
| 1674 } | 1637 } |
| 1675 | 1638 |
| 1676 void DumpField(RecordInfo* src, FieldPoint* point, const string& loc) { | 1639 void DumpField(RecordInfo* src, FieldPoint* point, const string& loc) { |
| 1677 src_ = src; | 1640 src_ = src; |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1868 | 1831 |
| 1869 void ReportClassContainsInvalidFields(RecordInfo* info, | 1832 void ReportClassContainsInvalidFields(RecordInfo* info, |
| 1870 CheckFieldsVisitor::Errors* errors) { | 1833 CheckFieldsVisitor::Errors* errors) { |
| 1871 SourceLocation loc = info->record()->getLocStart(); | 1834 SourceLocation loc = info->record()->getLocStart(); |
| 1872 SourceManager& manager = instance_.getSourceManager(); | 1835 SourceManager& manager = instance_.getSourceManager(); |
| 1873 FullSourceLoc full_loc(loc, manager); | 1836 FullSourceLoc full_loc(loc, manager); |
| 1874 bool only_warnings = options_.warn_raw_ptr; | 1837 bool only_warnings = options_.warn_raw_ptr; |
| 1875 for (CheckFieldsVisitor::Errors::iterator it = errors->begin(); | 1838 for (CheckFieldsVisitor::Errors::iterator it = errors->begin(); |
| 1876 only_warnings && it != errors->end(); | 1839 only_warnings && it != errors->end(); |
| 1877 ++it) { | 1840 ++it) { |
| 1878 if (!CheckFieldsVisitor::IsWarning(it->second)) | 1841 if (it->second != CheckFieldsVisitor::kRawPtrToGCManagedWarning) |
| 1879 only_warnings = false; | 1842 only_warnings = false; |
| 1880 } | 1843 } |
| 1881 diagnostic_.Report(full_loc, only_warnings ? | 1844 diagnostic_.Report(full_loc, only_warnings ? |
| 1882 diag_class_contains_invalid_fields_warning_ : | 1845 diag_class_contains_invalid_fields_warning_ : |
| 1883 diag_class_contains_invalid_fields_) | 1846 diag_class_contains_invalid_fields_) |
| 1884 << info->record(); | 1847 << info->record(); |
| 1885 for (CheckFieldsVisitor::Errors::iterator it = errors->begin(); | 1848 for (CheckFieldsVisitor::Errors::iterator it = errors->begin(); |
| 1886 it != errors->end(); | 1849 it != errors->end(); |
| 1887 ++it) { | 1850 ++it) { |
| 1888 unsigned error; | 1851 unsigned error; |
| 1889 if (CheckFieldsVisitor::IsRawPtrError(it->second)) { | 1852 if (it->second == CheckFieldsVisitor::kRawPtrToGCManaged || |
| 1853 it->second == CheckFieldsVisitor::kRawPtrToGCManagedWarning) { |
| 1890 error = diag_raw_ptr_to_gc_managed_class_note_; | 1854 error = diag_raw_ptr_to_gc_managed_class_note_; |
| 1891 } else if (CheckFieldsVisitor::IsReferencePtrError(it->second)) { | |
| 1892 error = diag_reference_ptr_to_gc_managed_class_note_; | |
| 1893 } else if (it->second == CheckFieldsVisitor::kRefPtrToGCManaged) { | 1855 } else if (it->second == CheckFieldsVisitor::kRefPtrToGCManaged) { |
| 1894 error = diag_ref_ptr_to_gc_managed_class_note_; | 1856 error = diag_ref_ptr_to_gc_managed_class_note_; |
| 1895 } else if (it->second == CheckFieldsVisitor::kOwnPtrToGCManaged) { | 1857 } else if (it->second == CheckFieldsVisitor::kOwnPtrToGCManaged) { |
| 1896 error = diag_own_ptr_to_gc_managed_class_note_; | 1858 error = diag_own_ptr_to_gc_managed_class_note_; |
| 1897 } else if (it->second == CheckFieldsVisitor::kMemberToGCUnmanaged) { | 1859 } else if (it->second == CheckFieldsVisitor::kMemberToGCUnmanaged) { |
| 1898 error = diag_member_to_gc_unmanaged_class_note_; | 1860 error = diag_member_to_gc_unmanaged_class_note_; |
| 1899 } else if (it->second == CheckFieldsVisitor::kMemberInUnmanaged) { | 1861 } else if (it->second == CheckFieldsVisitor::kMemberInUnmanaged) { |
| 1900 error = diag_member_in_unmanaged_class_note_; | 1862 error = diag_member_in_unmanaged_class_note_; |
| 1901 } else if (it->second == CheckFieldsVisitor::kPtrFromHeapToStack) { | 1863 } else if (it->second == CheckFieldsVisitor::kPtrFromHeapToStack) { |
| 1902 error = diag_stack_allocated_field_note_; | 1864 error = diag_stack_allocated_field_note_; |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2167 unsigned diag_class_overrides_new_; | 2129 unsigned diag_class_overrides_new_; |
| 2168 unsigned diag_class_declares_pure_virtual_trace_; | 2130 unsigned diag_class_declares_pure_virtual_trace_; |
| 2169 unsigned diag_left_most_base_must_be_polymorphic_; | 2131 unsigned diag_left_most_base_must_be_polymorphic_; |
| 2170 unsigned diag_base_class_must_declare_virtual_trace_; | 2132 unsigned diag_base_class_must_declare_virtual_trace_; |
| 2171 unsigned diag_class_must_declare_gc_mixin_trace_method_; | 2133 unsigned diag_class_must_declare_gc_mixin_trace_method_; |
| 2172 | 2134 |
| 2173 unsigned diag_base_requires_tracing_note_; | 2135 unsigned diag_base_requires_tracing_note_; |
| 2174 unsigned diag_field_requires_tracing_note_; | 2136 unsigned diag_field_requires_tracing_note_; |
| 2175 unsigned diag_raw_ptr_to_gc_managed_class_note_; | 2137 unsigned diag_raw_ptr_to_gc_managed_class_note_; |
| 2176 unsigned diag_ref_ptr_to_gc_managed_class_note_; | 2138 unsigned diag_ref_ptr_to_gc_managed_class_note_; |
| 2177 unsigned diag_reference_ptr_to_gc_managed_class_note_; | |
| 2178 unsigned diag_own_ptr_to_gc_managed_class_note_; | 2139 unsigned diag_own_ptr_to_gc_managed_class_note_; |
| 2179 unsigned diag_member_to_gc_unmanaged_class_note_; | 2140 unsigned diag_member_to_gc_unmanaged_class_note_; |
| 2180 unsigned diag_stack_allocated_field_note_; | 2141 unsigned diag_stack_allocated_field_note_; |
| 2181 unsigned diag_member_in_unmanaged_class_note_; | 2142 unsigned diag_member_in_unmanaged_class_note_; |
| 2182 unsigned diag_part_object_to_gc_derived_class_note_; | 2143 unsigned diag_part_object_to_gc_derived_class_note_; |
| 2183 unsigned diag_part_object_contains_gc_root_note_; | 2144 unsigned diag_part_object_contains_gc_root_note_; |
| 2184 unsigned diag_field_contains_gc_root_note_; | 2145 unsigned diag_field_contains_gc_root_note_; |
| 2185 unsigned diag_finalized_field_note_; | 2146 unsigned diag_finalized_field_note_; |
| 2186 unsigned diag_eagerly_finalized_field_note_; | 2147 unsigned diag_eagerly_finalized_field_note_; |
| 2187 unsigned diag_user_declared_destructor_note_; | 2148 unsigned diag_user_declared_destructor_note_; |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2234 | 2195 |
| 2235 private: | 2196 private: |
| 2236 BlinkGCPluginOptions options_; | 2197 BlinkGCPluginOptions options_; |
| 2237 }; | 2198 }; |
| 2238 | 2199 |
| 2239 } // namespace | 2200 } // namespace |
| 2240 | 2201 |
| 2241 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( | 2202 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( |
| 2242 "blink-gc-plugin", | 2203 "blink-gc-plugin", |
| 2243 "Check Blink GC invariants"); | 2204 "Check Blink GC invariants"); |
| OLD | NEW |