| 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 |
| 11 #include <algorithm> |
| 12 |
| 11 #include "Config.h" | 13 #include "Config.h" |
| 12 #include "JsonWriter.h" | 14 #include "JsonWriter.h" |
| 13 #include "RecordInfo.h" | 15 #include "RecordInfo.h" |
| 14 | 16 |
| 15 #include "clang/AST/AST.h" | 17 #include "clang/AST/AST.h" |
| 16 #include "clang/AST/ASTConsumer.h" | 18 #include "clang/AST/ASTConsumer.h" |
| 17 #include "clang/AST/RecursiveASTVisitor.h" | 19 #include "clang/AST/RecursiveASTVisitor.h" |
| 18 #include "clang/Frontend/CompilerInstance.h" | 20 #include "clang/Frontend/CompilerInstance.h" |
| 19 #include "clang/Frontend/FrontendPluginRegistry.h" | 21 #include "clang/Frontend/FrontendPluginRegistry.h" |
| 22 #include "clang/Sema/Sema.h" |
| 20 | 23 |
| 21 using namespace clang; | 24 using namespace clang; |
| 22 using std::string; | 25 using std::string; |
| 23 | 26 |
| 24 namespace { | 27 namespace { |
| 25 | 28 |
| 26 const char kClassMustLeftMostlyDeriveGC[] = | 29 const char kClassMustLeftMostlyDeriveGC[] = |
| 27 "[blink-gc] Class %0 must derive its GC base in the left-most position."; | 30 "[blink-gc] Class %0 must derive its GC base in the left-most position."; |
| 28 | 31 |
| 29 const char kClassRequiresTraceMethod[] = | 32 const char kClassRequiresTraceMethod[] = |
| (...skipping 19 matching lines...) Expand all Loading... |
| 49 | 52 |
| 50 const char kClassRequiresFinalization[] = | 53 const char kClassRequiresFinalization[] = |
| 51 "[blink-gc] Class %0 requires finalization."; | 54 "[blink-gc] Class %0 requires finalization."; |
| 52 | 55 |
| 53 const char kClassDoesNotRequireFinalization[] = | 56 const char kClassDoesNotRequireFinalization[] = |
| 54 "[blink-gc] Class %0 may not require finalization."; | 57 "[blink-gc] Class %0 may not require finalization."; |
| 55 | 58 |
| 56 const char kFinalizerAccessesFinalizedField[] = | 59 const char kFinalizerAccessesFinalizedField[] = |
| 57 "[blink-gc] Finalizer %0 accesses potentially finalized field %1."; | 60 "[blink-gc] Finalizer %0 accesses potentially finalized field %1."; |
| 58 | 61 |
| 62 const char kFinalizerAccessesEagerlyFinalizedField[] = |
| 63 "[blink-gc] Finalizer %0 accesses eagerly finalized field %1."; |
| 64 |
| 59 const char kRawPtrToGCManagedClassNote[] = | 65 const char kRawPtrToGCManagedClassNote[] = |
| 60 "[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:"; |
| 61 | 67 |
| 62 const char kRefPtrToGCManagedClassNote[] = | 68 const char kRefPtrToGCManagedClassNote[] = |
| 63 "[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:"; |
| 64 | 70 |
| 65 const char kOwnPtrToGCManagedClassNote[] = | 71 const char kOwnPtrToGCManagedClassNote[] = |
| 66 "[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:"; |
| 67 | 73 |
| 74 const char kMemberToGCUnmanagedClassNote[] = |
| 75 "[blink-gc] Member field %0 to non-GC managed class declared here:"; |
| 76 |
| 68 const char kStackAllocatedFieldNote[] = | 77 const char kStackAllocatedFieldNote[] = |
| 69 "[blink-gc] Stack-allocated field %0 declared here:"; | 78 "[blink-gc] Stack-allocated field %0 declared here:"; |
| 70 | 79 |
| 71 const char kMemberInUnmanagedClassNote[] = | 80 const char kMemberInUnmanagedClassNote[] = |
| 72 "[blink-gc] Member field %0 in unmanaged class declared here:"; | 81 "[blink-gc] Member field %0 in unmanaged class declared here:"; |
| 73 | 82 |
| 74 const char kPartObjectToGCDerivedClassNote[] = | 83 const char kPartObjectToGCDerivedClassNote[] = |
| 75 "[blink-gc] Part-object field %0 to a GC derived class declared here:"; | 84 "[blink-gc] Part-object field %0 to a GC derived class declared here:"; |
| 76 | 85 |
| 77 const char kPartObjectContainsGCRootNote[] = | 86 const char kPartObjectContainsGCRootNote[] = |
| (...skipping 20 matching lines...) Expand all Loading... |
| 98 | 107 |
| 99 const char kMissingTraceDispatch[] = | 108 const char kMissingTraceDispatch[] = |
| 100 "[blink-gc] Missing dispatch to class %0 in manual trace dispatch."; | 109 "[blink-gc] Missing dispatch to class %0 in manual trace dispatch."; |
| 101 | 110 |
| 102 const char kMissingFinalizeDispatch[] = | 111 const char kMissingFinalizeDispatch[] = |
| 103 "[blink-gc] Missing dispatch to class %0 in manual finalize dispatch."; | 112 "[blink-gc] Missing dispatch to class %0 in manual finalize dispatch."; |
| 104 | 113 |
| 105 const char kFinalizedFieldNote[] = | 114 const char kFinalizedFieldNote[] = |
| 106 "[blink-gc] Potentially finalized field %0 declared here:"; | 115 "[blink-gc] Potentially finalized field %0 declared here:"; |
| 107 | 116 |
| 117 const char kEagerlyFinalizedFieldNote[] = |
| 118 "[blink-gc] Field %0 having eagerly finalized value, declared here:"; |
| 119 |
| 108 const char kUserDeclaredDestructorNote[] = | 120 const char kUserDeclaredDestructorNote[] = |
| 109 "[blink-gc] User-declared destructor declared here:"; | 121 "[blink-gc] User-declared destructor declared here:"; |
| 110 | 122 |
| 111 const char kUserDeclaredFinalizerNote[] = | 123 const char kUserDeclaredFinalizerNote[] = |
| 112 "[blink-gc] User-declared finalizer declared here:"; | 124 "[blink-gc] User-declared finalizer declared here:"; |
| 113 | 125 |
| 114 const char kBaseRequiresFinalizationNote[] = | 126 const char kBaseRequiresFinalizationNote[] = |
| 115 "[blink-gc] Base class %0 requiring finalization declared here:"; | 127 "[blink-gc] Base class %0 requiring finalization declared here:"; |
| 116 | 128 |
| 117 const char kFieldRequiresFinalizationNote[] = | 129 const char kFieldRequiresFinalizationNote[] = |
| (...skipping 19 matching lines...) Expand all Loading... |
| 137 " must be polymorphic."; | 149 " must be polymorphic."; |
| 138 | 150 |
| 139 const char kBaseClassMustDeclareVirtualTrace[] = | 151 const char kBaseClassMustDeclareVirtualTrace[] = |
| 140 "[blink-gc] Left-most base class %0 of derived class %1" | 152 "[blink-gc] Left-most base class %0 of derived class %1" |
| 141 " must define a virtual trace method."; | 153 " must define a virtual trace method."; |
| 142 | 154 |
| 143 const char kClassMustDeclareGCMixinTraceMethod[] = | 155 const char kClassMustDeclareGCMixinTraceMethod[] = |
| 144 "[blink-gc] Class %0 which inherits from GarbageCollectedMixin must" | 156 "[blink-gc] Class %0 which inherits from GarbageCollectedMixin must" |
| 145 " locally declare and override trace(Visitor*)"; | 157 " locally declare and override trace(Visitor*)"; |
| 146 | 158 |
| 159 // Use a local RAV implementation to simply collect all FunctionDecls marked for |
| 160 // late template parsing. This happens with the flag -fdelayed-template-parsing, |
| 161 // which is on by default in MSVC-compatible mode. |
| 162 std::set<FunctionDecl*> GetLateParsedFunctionDecls(TranslationUnitDecl* decl) { |
| 163 struct Visitor : public RecursiveASTVisitor<Visitor> { |
| 164 bool VisitFunctionDecl(FunctionDecl* function_decl) { |
| 165 if (function_decl->isLateTemplateParsed()) |
| 166 late_parsed_decls.insert(function_decl); |
| 167 return true; |
| 168 } |
| 169 |
| 170 std::set<FunctionDecl*> late_parsed_decls; |
| 171 } v; |
| 172 v.TraverseDecl(decl); |
| 173 return v.late_parsed_decls; |
| 174 } |
| 175 |
| 147 struct BlinkGCPluginOptions { | 176 struct BlinkGCPluginOptions { |
| 148 BlinkGCPluginOptions() | 177 BlinkGCPluginOptions() |
| 149 : enable_oilpan(false) | 178 : enable_oilpan(false) |
| 150 , dump_graph(false) | 179 , dump_graph(false) |
| 151 , warn_raw_ptr(false) | 180 , warn_raw_ptr(false) |
| 152 , warn_unneeded_finalizer(false) {} | 181 , warn_unneeded_finalizer(false) {} |
| 153 bool enable_oilpan; | 182 bool enable_oilpan; |
| 154 bool dump_graph; | 183 bool dump_graph; |
| 155 bool warn_raw_ptr; | 184 bool warn_raw_ptr; |
| 156 bool warn_unneeded_finalizer; | 185 bool warn_unneeded_finalizer; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 // either a Member, a heap-allocated collection or an off-heap collection that | 245 // either a Member, a heap-allocated collection or an off-heap collection that |
| 217 // contains Members. Invalid uses are currently identified as passing the field | 246 // contains Members. Invalid uses are currently identified as passing the field |
| 218 // as the argument of a procedure call or using the -> or [] operators on it. | 247 // as the argument of a procedure call or using the -> or [] operators on it. |
| 219 class CheckFinalizerVisitor | 248 class CheckFinalizerVisitor |
| 220 : public RecursiveASTVisitor<CheckFinalizerVisitor> { | 249 : public RecursiveASTVisitor<CheckFinalizerVisitor> { |
| 221 private: | 250 private: |
| 222 // Simple visitor to determine if the content of a field might be collected | 251 // Simple visitor to determine if the content of a field might be collected |
| 223 // during finalization. | 252 // during finalization. |
| 224 class MightBeCollectedVisitor : public EdgeVisitor { | 253 class MightBeCollectedVisitor : public EdgeVisitor { |
| 225 public: | 254 public: |
| 226 MightBeCollectedVisitor() : might_be_collected_(false) {} | 255 MightBeCollectedVisitor(bool is_eagerly_finalized) |
| 256 : might_be_collected_(false) |
| 257 , is_eagerly_finalized_(is_eagerly_finalized) |
| 258 , as_eagerly_finalized_(false) {} |
| 227 bool might_be_collected() { return might_be_collected_; } | 259 bool might_be_collected() { return might_be_collected_; } |
| 228 void VisitMember(Member* edge) override { might_be_collected_ = true; } | 260 bool as_eagerly_finalized() { return as_eagerly_finalized_; } |
| 261 void VisitMember(Member* edge) override { |
| 262 if (is_eagerly_finalized_) { |
| 263 if (edge->ptr()->IsValue()) { |
| 264 Value* member = static_cast<Value*>(edge->ptr()); |
| 265 if (member->value()->IsEagerlyFinalized()) { |
| 266 might_be_collected_ = true; |
| 267 as_eagerly_finalized_ = true; |
| 268 } |
| 269 } |
| 270 return; |
| 271 } |
| 272 might_be_collected_ = true; |
| 273 } |
| 229 void VisitCollection(Collection* edge) override { | 274 void VisitCollection(Collection* edge) override { |
| 230 if (edge->on_heap()) { | 275 if (edge->on_heap() && !is_eagerly_finalized_) { |
| 231 might_be_collected_ = !edge->is_root(); | 276 might_be_collected_ = !edge->is_root(); |
| 232 } else { | 277 } else { |
| 233 edge->AcceptMembers(this); | 278 edge->AcceptMembers(this); |
| 234 } | 279 } |
| 235 } | 280 } |
| 236 | 281 |
| 237 private: | 282 private: |
| 238 bool might_be_collected_; | 283 bool might_be_collected_; |
| 284 bool is_eagerly_finalized_; |
| 285 bool as_eagerly_finalized_; |
| 239 }; | 286 }; |
| 240 | 287 |
| 241 public: | 288 public: |
| 242 typedef std::vector<std::pair<MemberExpr*, FieldPoint*> > Errors; | 289 class Error { |
| 290 public: |
| 291 Error(MemberExpr *member, |
| 292 bool as_eagerly_finalized, |
| 293 FieldPoint* field) |
| 294 : member_(member) |
| 295 , as_eagerly_finalized_(as_eagerly_finalized) |
| 296 , field_(field) {} |
| 243 | 297 |
| 244 CheckFinalizerVisitor(RecordCache* cache) | 298 MemberExpr* member_; |
| 245 : blacklist_context_(false), cache_(cache) {} | 299 bool as_eagerly_finalized_; |
| 300 FieldPoint* field_; |
| 301 }; |
| 302 |
| 303 typedef std::vector<Error> Errors; |
| 304 |
| 305 CheckFinalizerVisitor(RecordCache* cache, bool is_eagerly_finalized) |
| 306 : blacklist_context_(false) |
| 307 , cache_(cache) |
| 308 , is_eagerly_finalized_(is_eagerly_finalized) {} |
| 246 | 309 |
| 247 Errors& finalized_fields() { return finalized_fields_; } | 310 Errors& finalized_fields() { return finalized_fields_; } |
| 248 | 311 |
| 249 bool WalkUpFromCXXOperatorCallExpr(CXXOperatorCallExpr* expr) { | 312 bool WalkUpFromCXXOperatorCallExpr(CXXOperatorCallExpr* expr) { |
| 250 // Only continue the walk-up if the operator is a blacklisted one. | 313 // Only continue the walk-up if the operator is a blacklisted one. |
| 251 switch (expr->getOperator()) { | 314 switch (expr->getOperator()) { |
| 252 case OO_Arrow: | 315 case OO_Arrow: |
| 253 case OO_Subscript: | 316 case OO_Subscript: |
| 254 this->WalkUpFromCallExpr(expr); | 317 this->WalkUpFromCallExpr(expr); |
| 255 default: | 318 default: |
| (...skipping 17 matching lines...) Expand all Loading... |
| 273 return true; | 336 return true; |
| 274 | 337 |
| 275 RecordInfo* info = cache_->Lookup(field->getParent()); | 338 RecordInfo* info = cache_->Lookup(field->getParent()); |
| 276 if (!info) | 339 if (!info) |
| 277 return true; | 340 return true; |
| 278 | 341 |
| 279 RecordInfo::Fields::iterator it = info->GetFields().find(field); | 342 RecordInfo::Fields::iterator it = info->GetFields().find(field); |
| 280 if (it == info->GetFields().end()) | 343 if (it == info->GetFields().end()) |
| 281 return true; | 344 return true; |
| 282 | 345 |
| 283 if (blacklist_context_ && MightBeCollected(&it->second)) | 346 if (seen_members_.find(member) != seen_members_.end()) |
| 284 finalized_fields_.push_back(std::make_pair(member, &it->second)); | 347 return true; |
| 348 |
| 349 bool as_eagerly_finalized = false; |
| 350 if (blacklist_context_ && |
| 351 MightBeCollected(&it->second, as_eagerly_finalized)) { |
| 352 finalized_fields_.push_back( |
| 353 Error(member, as_eagerly_finalized, &it->second)); |
| 354 seen_members_.insert(member); |
| 355 } |
| 285 return true; | 356 return true; |
| 286 } | 357 } |
| 287 | 358 |
| 288 bool MightBeCollected(FieldPoint* point) { | 359 bool MightBeCollected(FieldPoint* point, bool& as_eagerly_finalized) { |
| 289 MightBeCollectedVisitor visitor; | 360 MightBeCollectedVisitor visitor(is_eagerly_finalized_); |
| 290 point->edge()->Accept(&visitor); | 361 point->edge()->Accept(&visitor); |
| 362 as_eagerly_finalized = visitor.as_eagerly_finalized(); |
| 291 return visitor.might_be_collected(); | 363 return visitor.might_be_collected(); |
| 292 } | 364 } |
| 293 | 365 |
| 294 private: | 366 private: |
| 295 bool blacklist_context_; | 367 bool blacklist_context_; |
| 296 Errors finalized_fields_; | 368 Errors finalized_fields_; |
| 369 std::set<MemberExpr*> seen_members_; |
| 297 RecordCache* cache_; | 370 RecordCache* cache_; |
| 371 bool is_eagerly_finalized_; |
| 298 }; | 372 }; |
| 299 | 373 |
| 300 // This visitor checks that a method contains within its body, a call to a | 374 // This visitor checks that a method contains within its body, a call to a |
| 301 // method on the provided receiver class. This is used to check manual | 375 // method on the provided receiver class. This is used to check manual |
| 302 // dispatching for trace and finalize methods. | 376 // dispatching for trace and finalize methods. |
| 303 class CheckDispatchVisitor : public RecursiveASTVisitor<CheckDispatchVisitor> { | 377 class CheckDispatchVisitor : public RecursiveASTVisitor<CheckDispatchVisitor> { |
| 304 public: | 378 public: |
| 305 CheckDispatchVisitor(RecordInfo* receiver) | 379 CheckDispatchVisitor(RecordInfo* receiver) |
| 306 : receiver_(receiver), dispatched_to_receiver_(false) {} | 380 : receiver_(receiver), dispatched_to_receiver_(false) {} |
| 307 | 381 |
| (...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 773 // - An on-heap class must never contain GC roots. | 847 // - An on-heap class must never contain GC roots. |
| 774 // - Only stack-allocated types may point to stack-allocated types. | 848 // - Only stack-allocated types may point to stack-allocated types. |
| 775 class CheckFieldsVisitor : public RecursiveEdgeVisitor { | 849 class CheckFieldsVisitor : public RecursiveEdgeVisitor { |
| 776 public: | 850 public: |
| 777 | 851 |
| 778 enum Error { | 852 enum Error { |
| 779 kRawPtrToGCManaged, | 853 kRawPtrToGCManaged, |
| 780 kRawPtrToGCManagedWarning, | 854 kRawPtrToGCManagedWarning, |
| 781 kRefPtrToGCManaged, | 855 kRefPtrToGCManaged, |
| 782 kOwnPtrToGCManaged, | 856 kOwnPtrToGCManaged, |
| 857 kMemberToGCUnmanaged, |
| 783 kMemberInUnmanaged, | 858 kMemberInUnmanaged, |
| 784 kPtrFromHeapToStack, | 859 kPtrFromHeapToStack, |
| 785 kGCDerivedPartObject | 860 kGCDerivedPartObject |
| 786 }; | 861 }; |
| 787 | 862 |
| 788 typedef std::vector<std::pair<FieldPoint*, Error> > Errors; | 863 typedef std::vector<std::pair<FieldPoint*, Error> > Errors; |
| 789 | 864 |
| 790 CheckFieldsVisitor(const BlinkGCPluginOptions& options) | 865 CheckFieldsVisitor(const BlinkGCPluginOptions& options) |
| 791 : options_(options), current_(0), stack_allocated_host_(false) {} | 866 : options_(options), current_(0), stack_allocated_host_(false) {} |
| 792 | 867 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 831 return; | 906 return; |
| 832 } | 907 } |
| 833 | 908 |
| 834 if (!Parent() && | 909 if (!Parent() && |
| 835 edge->value()->IsGCDerived() && | 910 edge->value()->IsGCDerived() && |
| 836 !edge->value()->IsGCMixin()) { | 911 !edge->value()->IsGCMixin()) { |
| 837 invalid_fields_.push_back(std::make_pair(current_, kGCDerivedPartObject)); | 912 invalid_fields_.push_back(std::make_pair(current_, kGCDerivedPartObject)); |
| 838 return; | 913 return; |
| 839 } | 914 } |
| 840 | 915 |
| 916 // If in a stack allocated context, be fairly insistent that T in Member<T> |
| 917 // is GC allocated, as stack allocated objects do not have a trace() |
| 918 // that separately verifies the validity of Member<T>. |
| 919 // |
| 920 // Notice that an error is only reported if T's definition is in scope; |
| 921 // we do not require that it must be brought into scope as that would |
| 922 // prevent declarations of mutually dependent class types. |
| 923 // |
| 924 // (Note: Member<>'s constructor will at run-time verify that the |
| 925 // pointer it wraps is indeed heap allocated.) |
| 926 if (stack_allocated_host_ && Parent() && Parent()->IsMember() && |
| 927 edge->value()->HasDefinition() && !edge->value()->IsGCAllocated()) { |
| 928 invalid_fields_.push_back(std::make_pair(current_, |
| 929 kMemberToGCUnmanaged)); |
| 930 return; |
| 931 } |
| 932 |
| 841 if (!Parent() || !edge->value()->IsGCAllocated()) | 933 if (!Parent() || !edge->value()->IsGCAllocated()) |
| 842 return; | 934 return; |
| 843 | 935 |
| 844 // In transition mode, disallow OwnPtr<T>, RawPtr<T> to GC allocated T's, | 936 // In transition mode, disallow OwnPtr<T>, RawPtr<T> to GC allocated T's, |
| 845 // also disallow T* in stack-allocated types. | 937 // also disallow T* in stack-allocated types. |
| 846 if (options_.enable_oilpan) { | 938 if (options_.enable_oilpan) { |
| 847 if (Parent()->IsOwnPtr() || | 939 if (Parent()->IsOwnPtr() || |
| 848 Parent()->IsRawPtrClass() || | 940 Parent()->IsRawPtrClass() || |
| 849 (stack_allocated_host_ && Parent()->IsRawPtr())) { | 941 (stack_allocated_host_ && Parent()->IsRawPtr())) { |
| 850 invalid_fields_.push_back(std::make_pair( | 942 invalid_fields_.push_back(std::make_pair( |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 942 diag_class_contains_invalid_fields_warning_ = diagnostic_.getCustomDiagID( | 1034 diag_class_contains_invalid_fields_warning_ = diagnostic_.getCustomDiagID( |
| 943 DiagnosticsEngine::Warning, kClassContainsInvalidFields); | 1035 DiagnosticsEngine::Warning, kClassContainsInvalidFields); |
| 944 diag_class_contains_gc_root_ = | 1036 diag_class_contains_gc_root_ = |
| 945 diagnostic_.getCustomDiagID(getErrorLevel(), kClassContainsGCRoot); | 1037 diagnostic_.getCustomDiagID(getErrorLevel(), kClassContainsGCRoot); |
| 946 diag_class_requires_finalization_ = diagnostic_.getCustomDiagID( | 1038 diag_class_requires_finalization_ = diagnostic_.getCustomDiagID( |
| 947 getErrorLevel(), kClassRequiresFinalization); | 1039 getErrorLevel(), kClassRequiresFinalization); |
| 948 diag_class_does_not_require_finalization_ = diagnostic_.getCustomDiagID( | 1040 diag_class_does_not_require_finalization_ = diagnostic_.getCustomDiagID( |
| 949 DiagnosticsEngine::Warning, kClassDoesNotRequireFinalization); | 1041 DiagnosticsEngine::Warning, kClassDoesNotRequireFinalization); |
| 950 diag_finalizer_accesses_finalized_field_ = diagnostic_.getCustomDiagID( | 1042 diag_finalizer_accesses_finalized_field_ = diagnostic_.getCustomDiagID( |
| 951 getErrorLevel(), kFinalizerAccessesFinalizedField); | 1043 getErrorLevel(), kFinalizerAccessesFinalizedField); |
| 1044 diag_finalizer_eagerly_finalized_field_ = diagnostic_.getCustomDiagID( |
| 1045 getErrorLevel(), kFinalizerAccessesEagerlyFinalizedField); |
| 952 diag_overridden_non_virtual_trace_ = diagnostic_.getCustomDiagID( | 1046 diag_overridden_non_virtual_trace_ = diagnostic_.getCustomDiagID( |
| 953 getErrorLevel(), kOverriddenNonVirtualTrace); | 1047 getErrorLevel(), kOverriddenNonVirtualTrace); |
| 954 diag_missing_trace_dispatch_method_ = diagnostic_.getCustomDiagID( | 1048 diag_missing_trace_dispatch_method_ = diagnostic_.getCustomDiagID( |
| 955 getErrorLevel(), kMissingTraceDispatchMethod); | 1049 getErrorLevel(), kMissingTraceDispatchMethod); |
| 956 diag_missing_finalize_dispatch_method_ = diagnostic_.getCustomDiagID( | 1050 diag_missing_finalize_dispatch_method_ = diagnostic_.getCustomDiagID( |
| 957 getErrorLevel(), kMissingFinalizeDispatchMethod); | 1051 getErrorLevel(), kMissingFinalizeDispatchMethod); |
| 958 diag_virtual_and_manual_dispatch_ = | 1052 diag_virtual_and_manual_dispatch_ = |
| 959 diagnostic_.getCustomDiagID(getErrorLevel(), kVirtualAndManualDispatch); | 1053 diagnostic_.getCustomDiagID(getErrorLevel(), kVirtualAndManualDispatch); |
| 960 diag_missing_trace_dispatch_ = | 1054 diag_missing_trace_dispatch_ = |
| 961 diagnostic_.getCustomDiagID(getErrorLevel(), kMissingTraceDispatch); | 1055 diagnostic_.getCustomDiagID(getErrorLevel(), kMissingTraceDispatch); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 979 diag_base_requires_tracing_note_ = diagnostic_.getCustomDiagID( | 1073 diag_base_requires_tracing_note_ = diagnostic_.getCustomDiagID( |
| 980 DiagnosticsEngine::Note, kBaseRequiresTracingNote); | 1074 DiagnosticsEngine::Note, kBaseRequiresTracingNote); |
| 981 diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID( | 1075 diag_field_requires_tracing_note_ = diagnostic_.getCustomDiagID( |
| 982 DiagnosticsEngine::Note, kFieldRequiresTracingNote); | 1076 DiagnosticsEngine::Note, kFieldRequiresTracingNote); |
| 983 diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 1077 diag_raw_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
| 984 DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote); | 1078 DiagnosticsEngine::Note, kRawPtrToGCManagedClassNote); |
| 985 diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 1079 diag_ref_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
| 986 DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote); | 1080 DiagnosticsEngine::Note, kRefPtrToGCManagedClassNote); |
| 987 diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( | 1081 diag_own_ptr_to_gc_managed_class_note_ = diagnostic_.getCustomDiagID( |
| 988 DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote); | 1082 DiagnosticsEngine::Note, kOwnPtrToGCManagedClassNote); |
| 1083 diag_member_to_gc_unmanaged_class_note_ = diagnostic_.getCustomDiagID( |
| 1084 DiagnosticsEngine::Note, kMemberToGCUnmanagedClassNote); |
| 989 diag_stack_allocated_field_note_ = diagnostic_.getCustomDiagID( | 1085 diag_stack_allocated_field_note_ = diagnostic_.getCustomDiagID( |
| 990 DiagnosticsEngine::Note, kStackAllocatedFieldNote); | 1086 DiagnosticsEngine::Note, kStackAllocatedFieldNote); |
| 991 diag_member_in_unmanaged_class_note_ = diagnostic_.getCustomDiagID( | 1087 diag_member_in_unmanaged_class_note_ = diagnostic_.getCustomDiagID( |
| 992 DiagnosticsEngine::Note, kMemberInUnmanagedClassNote); | 1088 DiagnosticsEngine::Note, kMemberInUnmanagedClassNote); |
| 993 diag_part_object_to_gc_derived_class_note_ = diagnostic_.getCustomDiagID( | 1089 diag_part_object_to_gc_derived_class_note_ = diagnostic_.getCustomDiagID( |
| 994 DiagnosticsEngine::Note, kPartObjectToGCDerivedClassNote); | 1090 DiagnosticsEngine::Note, kPartObjectToGCDerivedClassNote); |
| 995 diag_part_object_contains_gc_root_note_ = diagnostic_.getCustomDiagID( | 1091 diag_part_object_contains_gc_root_note_ = diagnostic_.getCustomDiagID( |
| 996 DiagnosticsEngine::Note, kPartObjectContainsGCRootNote); | 1092 DiagnosticsEngine::Note, kPartObjectContainsGCRootNote); |
| 997 diag_field_contains_gc_root_note_ = diagnostic_.getCustomDiagID( | 1093 diag_field_contains_gc_root_note_ = diagnostic_.getCustomDiagID( |
| 998 DiagnosticsEngine::Note, kFieldContainsGCRootNote); | 1094 DiagnosticsEngine::Note, kFieldContainsGCRootNote); |
| 999 diag_finalized_field_note_ = diagnostic_.getCustomDiagID( | 1095 diag_finalized_field_note_ = diagnostic_.getCustomDiagID( |
| 1000 DiagnosticsEngine::Note, kFinalizedFieldNote); | 1096 DiagnosticsEngine::Note, kFinalizedFieldNote); |
| 1097 diag_eagerly_finalized_field_note_ = diagnostic_.getCustomDiagID( |
| 1098 DiagnosticsEngine::Note, kEagerlyFinalizedFieldNote); |
| 1001 diag_user_declared_destructor_note_ = diagnostic_.getCustomDiagID( | 1099 diag_user_declared_destructor_note_ = diagnostic_.getCustomDiagID( |
| 1002 DiagnosticsEngine::Note, kUserDeclaredDestructorNote); | 1100 DiagnosticsEngine::Note, kUserDeclaredDestructorNote); |
| 1003 diag_user_declared_finalizer_note_ = diagnostic_.getCustomDiagID( | 1101 diag_user_declared_finalizer_note_ = diagnostic_.getCustomDiagID( |
| 1004 DiagnosticsEngine::Note, kUserDeclaredFinalizerNote); | 1102 DiagnosticsEngine::Note, kUserDeclaredFinalizerNote); |
| 1005 diag_base_requires_finalization_note_ = diagnostic_.getCustomDiagID( | 1103 diag_base_requires_finalization_note_ = diagnostic_.getCustomDiagID( |
| 1006 DiagnosticsEngine::Note, kBaseRequiresFinalizationNote); | 1104 DiagnosticsEngine::Note, kBaseRequiresFinalizationNote); |
| 1007 diag_field_requires_finalization_note_ = diagnostic_.getCustomDiagID( | 1105 diag_field_requires_finalization_note_ = diagnostic_.getCustomDiagID( |
| 1008 DiagnosticsEngine::Note, kFieldRequiresFinalizationNote); | 1106 DiagnosticsEngine::Note, kFieldRequiresFinalizationNote); |
| 1009 diag_overridden_non_virtual_trace_note_ = diagnostic_.getCustomDiagID( | 1107 diag_overridden_non_virtual_trace_note_ = diagnostic_.getCustomDiagID( |
| 1010 DiagnosticsEngine::Note, kOverriddenNonVirtualTraceNote); | 1108 DiagnosticsEngine::Note, kOverriddenNonVirtualTraceNote); |
| 1011 diag_manual_dispatch_method_note_ = diagnostic_.getCustomDiagID( | 1109 diag_manual_dispatch_method_note_ = diagnostic_.getCustomDiagID( |
| 1012 DiagnosticsEngine::Note, kManualDispatchMethodNote); | 1110 DiagnosticsEngine::Note, kManualDispatchMethodNote); |
| 1013 } | 1111 } |
| 1014 | 1112 |
| 1015 void HandleTranslationUnit(ASTContext& context) override { | 1113 void HandleTranslationUnit(ASTContext& context) override { |
| 1016 // Don't run the plugin if the compilation unit is already invalid. | 1114 // Don't run the plugin if the compilation unit is already invalid. |
| 1017 if (diagnostic_.hasErrorOccurred()) | 1115 if (diagnostic_.hasErrorOccurred()) |
| 1018 return; | 1116 return; |
| 1019 | 1117 |
| 1118 ParseFunctionTemplates(context.getTranslationUnitDecl()); |
| 1119 |
| 1020 CollectVisitor visitor; | 1120 CollectVisitor visitor; |
| 1021 visitor.TraverseDecl(context.getTranslationUnitDecl()); | 1121 visitor.TraverseDecl(context.getTranslationUnitDecl()); |
| 1022 | 1122 |
| 1023 if (options_.dump_graph) { | 1123 if (options_.dump_graph) { |
| 1024 std::error_code err; | 1124 std::error_code err; |
| 1025 // TODO: Make createDefaultOutputFile or a shorter createOutputFile work. | 1125 // TODO: Make createDefaultOutputFile or a shorter createOutputFile work. |
| 1026 json_ = JsonWriter::from(instance_.createOutputFile( | 1126 json_ = JsonWriter::from(instance_.createOutputFile( |
| 1027 "", // OutputPath | 1127 "", // OutputPath |
| 1028 err, // Errors | 1128 err, // Errors |
| 1029 true, // Binary | 1129 true, // Binary |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1056 CheckTracingMethod(*it); | 1156 CheckTracingMethod(*it); |
| 1057 } | 1157 } |
| 1058 | 1158 |
| 1059 if (json_) { | 1159 if (json_) { |
| 1060 json_->CloseList(); | 1160 json_->CloseList(); |
| 1061 delete json_; | 1161 delete json_; |
| 1062 json_ = 0; | 1162 json_ = 0; |
| 1063 } | 1163 } |
| 1064 } | 1164 } |
| 1065 | 1165 |
| 1166 void ParseFunctionTemplates(TranslationUnitDecl* decl) { |
| 1167 if (!instance_.getLangOpts().DelayedTemplateParsing) |
| 1168 return; // Nothing to do. |
| 1169 |
| 1170 std::set<FunctionDecl*> late_parsed_decls = |
| 1171 GetLateParsedFunctionDecls(decl); |
| 1172 clang::Sema& sema = instance_.getSema(); |
| 1173 |
| 1174 for (const FunctionDecl* fd : late_parsed_decls) { |
| 1175 assert(fd->isLateTemplateParsed()); |
| 1176 |
| 1177 if (!Config::IsTraceMethod(fd)) |
| 1178 continue; |
| 1179 |
| 1180 if (instance_.getSourceManager().isInSystemHeader( |
| 1181 instance_.getSourceManager().getSpellingLoc(fd->getLocation()))) |
| 1182 continue; |
| 1183 |
| 1184 // Force parsing and AST building of the yet-uninstantiated function |
| 1185 // template trace method bodies. |
| 1186 clang::LateParsedTemplate* lpt = sema.LateParsedTemplateMap[fd]; |
| 1187 sema.LateTemplateParser(sema.OpaqueParser, *lpt); |
| 1188 } |
| 1189 } |
| 1190 |
| 1066 // Main entry for checking a record declaration. | 1191 // Main entry for checking a record declaration. |
| 1067 void CheckRecord(RecordInfo* info) { | 1192 void CheckRecord(RecordInfo* info) { |
| 1068 if (IsIgnored(info)) | 1193 if (IsIgnored(info)) |
| 1069 return; | 1194 return; |
| 1070 | 1195 |
| 1071 CXXRecordDecl* record = info->record(); | 1196 CXXRecordDecl* record = info->record(); |
| 1072 | 1197 |
| 1073 // TODO: what should we do to check unions? | 1198 // TODO: what should we do to check unions? |
| 1074 if (record->isUnion()) | 1199 if (record->isUnion()) |
| 1075 return; | 1200 return; |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1333 } | 1458 } |
| 1334 } | 1459 } |
| 1335 | 1460 |
| 1336 // TODO: Should we collect destructors similar to trace methods? | 1461 // TODO: Should we collect destructors similar to trace methods? |
| 1337 void CheckFinalization(RecordInfo* info) { | 1462 void CheckFinalization(RecordInfo* info) { |
| 1338 CXXDestructorDecl* dtor = info->record()->getDestructor(); | 1463 CXXDestructorDecl* dtor = info->record()->getDestructor(); |
| 1339 | 1464 |
| 1340 // For finalized classes, check the finalization method if possible. | 1465 // For finalized classes, check the finalization method if possible. |
| 1341 if (info->IsGCFinalized()) { | 1466 if (info->IsGCFinalized()) { |
| 1342 if (dtor && dtor->hasBody()) { | 1467 if (dtor && dtor->hasBody()) { |
| 1343 CheckFinalizerVisitor visitor(&cache_); | 1468 CheckFinalizerVisitor visitor(&cache_, info->IsEagerlyFinalized()); |
| 1344 visitor.TraverseCXXMethodDecl(dtor); | 1469 visitor.TraverseCXXMethodDecl(dtor); |
| 1345 if (!visitor.finalized_fields().empty()) { | 1470 if (!visitor.finalized_fields().empty()) { |
| 1346 ReportFinalizerAccessesFinalizedFields( | 1471 ReportFinalizerAccessesFinalizedFields( |
| 1347 dtor, &visitor.finalized_fields()); | 1472 dtor, &visitor.finalized_fields()); |
| 1348 } | 1473 } |
| 1349 } | 1474 } |
| 1350 return; | 1475 return; |
| 1351 } | 1476 } |
| 1352 | 1477 |
| 1353 // Don't require finalization of a mixin that has not yet been "mixed in". | 1478 // Don't require finalization of a mixin that has not yet been "mixed in". |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1603 if (info->name().compare(0, SameSizeAs.size(), SameSizeAs) == 0) | 1728 if (info->name().compare(0, SameSizeAs.size(), SameSizeAs) == 0) |
| 1604 return true; | 1729 return true; |
| 1605 return options_.ignored_classes.find(info->name()) != | 1730 return options_.ignored_classes.find(info->name()) != |
| 1606 options_.ignored_classes.end(); | 1731 options_.ignored_classes.end(); |
| 1607 } | 1732 } |
| 1608 | 1733 |
| 1609 bool InIgnoredDirectory(RecordInfo* info) { | 1734 bool InIgnoredDirectory(RecordInfo* info) { |
| 1610 string filename; | 1735 string filename; |
| 1611 if (!GetFilename(info->record()->getLocStart(), &filename)) | 1736 if (!GetFilename(info->record()->getLocStart(), &filename)) |
| 1612 return false; // TODO: should we ignore non-existing file locations? | 1737 return false; // TODO: should we ignore non-existing file locations? |
| 1738 #if defined(LLVM_ON_WIN32) |
| 1739 std::replace(filename.begin(), filename.end(), '\\', '/'); |
| 1740 #endif |
| 1613 std::vector<string>::iterator it = options_.ignored_directories.begin(); | 1741 std::vector<string>::iterator it = options_.ignored_directories.begin(); |
| 1614 for (; it != options_.ignored_directories.end(); ++it) | 1742 for (; it != options_.ignored_directories.end(); ++it) |
| 1615 if (filename.find(*it) != string::npos) | 1743 if (filename.find(*it) != string::npos) |
| 1616 return true; | 1744 return true; |
| 1617 return false; | 1745 return false; |
| 1618 } | 1746 } |
| 1619 | 1747 |
| 1620 bool InCheckedNamespace(RecordInfo* info) { | 1748 bool InCheckedNamespace(RecordInfo* info) { |
| 1621 if (!info) | 1749 if (!info) |
| 1622 return false; | 1750 return false; |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1720 it != errors->end(); | 1848 it != errors->end(); |
| 1721 ++it) { | 1849 ++it) { |
| 1722 unsigned error; | 1850 unsigned error; |
| 1723 if (it->second == CheckFieldsVisitor::kRawPtrToGCManaged || | 1851 if (it->second == CheckFieldsVisitor::kRawPtrToGCManaged || |
| 1724 it->second == CheckFieldsVisitor::kRawPtrToGCManagedWarning) { | 1852 it->second == CheckFieldsVisitor::kRawPtrToGCManagedWarning) { |
| 1725 error = diag_raw_ptr_to_gc_managed_class_note_; | 1853 error = diag_raw_ptr_to_gc_managed_class_note_; |
| 1726 } else if (it->second == CheckFieldsVisitor::kRefPtrToGCManaged) { | 1854 } else if (it->second == CheckFieldsVisitor::kRefPtrToGCManaged) { |
| 1727 error = diag_ref_ptr_to_gc_managed_class_note_; | 1855 error = diag_ref_ptr_to_gc_managed_class_note_; |
| 1728 } else if (it->second == CheckFieldsVisitor::kOwnPtrToGCManaged) { | 1856 } else if (it->second == CheckFieldsVisitor::kOwnPtrToGCManaged) { |
| 1729 error = diag_own_ptr_to_gc_managed_class_note_; | 1857 error = diag_own_ptr_to_gc_managed_class_note_; |
| 1858 } else if (it->second == CheckFieldsVisitor::kMemberToGCUnmanaged) { |
| 1859 error = diag_member_to_gc_unmanaged_class_note_; |
| 1730 } else if (it->second == CheckFieldsVisitor::kMemberInUnmanaged) { | 1860 } else if (it->second == CheckFieldsVisitor::kMemberInUnmanaged) { |
| 1731 error = diag_member_in_unmanaged_class_note_; | 1861 error = diag_member_in_unmanaged_class_note_; |
| 1732 } else if (it->second == CheckFieldsVisitor::kPtrFromHeapToStack) { | 1862 } else if (it->second == CheckFieldsVisitor::kPtrFromHeapToStack) { |
| 1733 error = diag_stack_allocated_field_note_; | 1863 error = diag_stack_allocated_field_note_; |
| 1734 } else if (it->second == CheckFieldsVisitor::kGCDerivedPartObject) { | 1864 } else if (it->second == CheckFieldsVisitor::kGCDerivedPartObject) { |
| 1735 error = diag_part_object_to_gc_derived_class_note_; | 1865 error = diag_part_object_to_gc_derived_class_note_; |
| 1736 } else { | 1866 } else { |
| 1737 assert(false && "Unknown field error"); | 1867 assert(false && "Unknown field error"); |
| 1738 } | 1868 } |
| 1739 NoteField(it->first, error); | 1869 NoteField(it->first, error); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1759 NoteFieldContainsGCRoot(point); | 1889 NoteFieldContainsGCRoot(point); |
| 1760 } | 1890 } |
| 1761 } | 1891 } |
| 1762 | 1892 |
| 1763 void ReportFinalizerAccessesFinalizedFields( | 1893 void ReportFinalizerAccessesFinalizedFields( |
| 1764 CXXMethodDecl* dtor, | 1894 CXXMethodDecl* dtor, |
| 1765 CheckFinalizerVisitor::Errors* fields) { | 1895 CheckFinalizerVisitor::Errors* fields) { |
| 1766 for (CheckFinalizerVisitor::Errors::iterator it = fields->begin(); | 1896 for (CheckFinalizerVisitor::Errors::iterator it = fields->begin(); |
| 1767 it != fields->end(); | 1897 it != fields->end(); |
| 1768 ++it) { | 1898 ++it) { |
| 1769 SourceLocation loc = it->first->getLocStart(); | 1899 SourceLocation loc = it->member_->getLocStart(); |
| 1770 SourceManager& manager = instance_.getSourceManager(); | 1900 SourceManager& manager = instance_.getSourceManager(); |
| 1901 bool as_eagerly_finalized = it->as_eagerly_finalized_; |
| 1902 unsigned diag_error = as_eagerly_finalized ? |
| 1903 diag_finalizer_eagerly_finalized_field_ : |
| 1904 diag_finalizer_accesses_finalized_field_; |
| 1905 unsigned diag_note = as_eagerly_finalized ? |
| 1906 diag_eagerly_finalized_field_note_ : |
| 1907 diag_finalized_field_note_; |
| 1771 FullSourceLoc full_loc(loc, manager); | 1908 FullSourceLoc full_loc(loc, manager); |
| 1772 diagnostic_.Report(full_loc, diag_finalizer_accesses_finalized_field_) | 1909 diagnostic_.Report(full_loc, diag_error) |
| 1773 << dtor << it->second->field(); | 1910 << dtor << it->field_->field(); |
| 1774 NoteField(it->second, diag_finalized_field_note_); | 1911 NoteField(it->field_, diag_note); |
| 1775 } | 1912 } |
| 1776 } | 1913 } |
| 1777 | 1914 |
| 1778 void ReportClassRequiresFinalization(RecordInfo* info) { | 1915 void ReportClassRequiresFinalization(RecordInfo* info) { |
| 1779 SourceLocation loc = info->record()->getInnerLocStart(); | 1916 SourceLocation loc = info->record()->getInnerLocStart(); |
| 1780 SourceManager& manager = instance_.getSourceManager(); | 1917 SourceManager& manager = instance_.getSourceManager(); |
| 1781 FullSourceLoc full_loc(loc, manager); | 1918 FullSourceLoc full_loc(loc, manager); |
| 1782 diagnostic_.Report(full_loc, diag_class_requires_finalization_) | 1919 diagnostic_.Report(full_loc, diag_class_requires_finalization_) |
| 1783 << info->record(); | 1920 << info->record(); |
| 1784 } | 1921 } |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1973 unsigned diag_class_must_left_mostly_derive_gc_; | 2110 unsigned diag_class_must_left_mostly_derive_gc_; |
| 1974 unsigned diag_class_requires_trace_method_; | 2111 unsigned diag_class_requires_trace_method_; |
| 1975 unsigned diag_base_requires_tracing_; | 2112 unsigned diag_base_requires_tracing_; |
| 1976 unsigned diag_fields_require_tracing_; | 2113 unsigned diag_fields_require_tracing_; |
| 1977 unsigned diag_class_contains_invalid_fields_; | 2114 unsigned diag_class_contains_invalid_fields_; |
| 1978 unsigned diag_class_contains_invalid_fields_warning_; | 2115 unsigned diag_class_contains_invalid_fields_warning_; |
| 1979 unsigned diag_class_contains_gc_root_; | 2116 unsigned diag_class_contains_gc_root_; |
| 1980 unsigned diag_class_requires_finalization_; | 2117 unsigned diag_class_requires_finalization_; |
| 1981 unsigned diag_class_does_not_require_finalization_; | 2118 unsigned diag_class_does_not_require_finalization_; |
| 1982 unsigned diag_finalizer_accesses_finalized_field_; | 2119 unsigned diag_finalizer_accesses_finalized_field_; |
| 2120 unsigned diag_finalizer_eagerly_finalized_field_; |
| 1983 unsigned diag_overridden_non_virtual_trace_; | 2121 unsigned diag_overridden_non_virtual_trace_; |
| 1984 unsigned diag_missing_trace_dispatch_method_; | 2122 unsigned diag_missing_trace_dispatch_method_; |
| 1985 unsigned diag_missing_finalize_dispatch_method_; | 2123 unsigned diag_missing_finalize_dispatch_method_; |
| 1986 unsigned diag_virtual_and_manual_dispatch_; | 2124 unsigned diag_virtual_and_manual_dispatch_; |
| 1987 unsigned diag_missing_trace_dispatch_; | 2125 unsigned diag_missing_trace_dispatch_; |
| 1988 unsigned diag_missing_finalize_dispatch_; | 2126 unsigned diag_missing_finalize_dispatch_; |
| 1989 unsigned diag_derives_non_stack_allocated_; | 2127 unsigned diag_derives_non_stack_allocated_; |
| 1990 unsigned diag_class_overrides_new_; | 2128 unsigned diag_class_overrides_new_; |
| 1991 unsigned diag_class_declares_pure_virtual_trace_; | 2129 unsigned diag_class_declares_pure_virtual_trace_; |
| 1992 unsigned diag_left_most_base_must_be_polymorphic_; | 2130 unsigned diag_left_most_base_must_be_polymorphic_; |
| 1993 unsigned diag_base_class_must_declare_virtual_trace_; | 2131 unsigned diag_base_class_must_declare_virtual_trace_; |
| 1994 unsigned diag_class_must_declare_gc_mixin_trace_method_; | 2132 unsigned diag_class_must_declare_gc_mixin_trace_method_; |
| 1995 | 2133 |
| 1996 unsigned diag_base_requires_tracing_note_; | 2134 unsigned diag_base_requires_tracing_note_; |
| 1997 unsigned diag_field_requires_tracing_note_; | 2135 unsigned diag_field_requires_tracing_note_; |
| 1998 unsigned diag_raw_ptr_to_gc_managed_class_note_; | 2136 unsigned diag_raw_ptr_to_gc_managed_class_note_; |
| 1999 unsigned diag_ref_ptr_to_gc_managed_class_note_; | 2137 unsigned diag_ref_ptr_to_gc_managed_class_note_; |
| 2000 unsigned diag_own_ptr_to_gc_managed_class_note_; | 2138 unsigned diag_own_ptr_to_gc_managed_class_note_; |
| 2139 unsigned diag_member_to_gc_unmanaged_class_note_; |
| 2001 unsigned diag_stack_allocated_field_note_; | 2140 unsigned diag_stack_allocated_field_note_; |
| 2002 unsigned diag_member_in_unmanaged_class_note_; | 2141 unsigned diag_member_in_unmanaged_class_note_; |
| 2003 unsigned diag_part_object_to_gc_derived_class_note_; | 2142 unsigned diag_part_object_to_gc_derived_class_note_; |
| 2004 unsigned diag_part_object_contains_gc_root_note_; | 2143 unsigned diag_part_object_contains_gc_root_note_; |
| 2005 unsigned diag_field_contains_gc_root_note_; | 2144 unsigned diag_field_contains_gc_root_note_; |
| 2006 unsigned diag_finalized_field_note_; | 2145 unsigned diag_finalized_field_note_; |
| 2146 unsigned diag_eagerly_finalized_field_note_; |
| 2007 unsigned diag_user_declared_destructor_note_; | 2147 unsigned diag_user_declared_destructor_note_; |
| 2008 unsigned diag_user_declared_finalizer_note_; | 2148 unsigned diag_user_declared_finalizer_note_; |
| 2009 unsigned diag_base_requires_finalization_note_; | 2149 unsigned diag_base_requires_finalization_note_; |
| 2010 unsigned diag_field_requires_finalization_note_; | 2150 unsigned diag_field_requires_finalization_note_; |
| 2011 unsigned diag_overridden_non_virtual_trace_note_; | 2151 unsigned diag_overridden_non_virtual_trace_note_; |
| 2012 unsigned diag_manual_dispatch_method_note_; | 2152 unsigned diag_manual_dispatch_method_note_; |
| 2013 | 2153 |
| 2014 CompilerInstance& instance_; | 2154 CompilerInstance& instance_; |
| 2015 DiagnosticsEngine& diagnostic_; | 2155 DiagnosticsEngine& diagnostic_; |
| 2016 BlinkGCPluginOptions options_; | 2156 BlinkGCPluginOptions options_; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2054 | 2194 |
| 2055 private: | 2195 private: |
| 2056 BlinkGCPluginOptions options_; | 2196 BlinkGCPluginOptions options_; |
| 2057 }; | 2197 }; |
| 2058 | 2198 |
| 2059 } // namespace | 2199 } // namespace |
| 2060 | 2200 |
| 2061 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( | 2201 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( |
| 2062 "blink-gc-plugin", | 2202 "blink-gc-plugin", |
| 2063 "Check Blink GC invariants"); | 2203 "Check Blink GC invariants"); |
| OLD | NEW |