Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(233)

Side by Side Diff: tools/clang/blink_gc_plugin/BlinkGCPlugin.cpp

Issue 564453002: Blink GC plugin: Check polymorphic requirements on all GC-derived classes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase and fix test error from previous CL Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | tools/clang/blink_gc_plugin/tests/class_does_not_require_finalization.txt » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 933 matching lines...) Expand 10 before | Expand all | Expand 10 after
944 it != info->GetBases().end(); 944 it != info->GetBases().end();
945 ++it) { 945 ++it) {
946 if (!it->second.info()->IsStackAllocated()) 946 if (!it->second.info()->IsStackAllocated())
947 ReportDerivesNonStackAllocated(info, &it->second); 947 ReportDerivesNonStackAllocated(info, &it->second);
948 } 948 }
949 } 949 }
950 950
951 if (CXXMethodDecl* trace = info->GetTraceMethod()) { 951 if (CXXMethodDecl* trace = info->GetTraceMethod()) {
952 if (trace->isPure()) 952 if (trace->isPure())
953 ReportClassDeclaresPureVirtualTrace(info, trace); 953 ReportClassDeclaresPureVirtualTrace(info, trace);
954 if (info->record()->isPolymorphic())
955 CheckPolymorphicClass(info, trace);
956 } else if (info->RequiresTraceMethod()) { 954 } else if (info->RequiresTraceMethod()) {
957 ReportClassRequiresTraceMethod(info); 955 ReportClassRequiresTraceMethod(info);
958 } 956 }
959 957
958 // Check polymorphic classes that are GC-derived or have a trace method.
959 if (info->record()->hasDefinition() && info->record()->isPolymorphic()) {
960 CXXMethodDecl* trace = info->GetTraceMethod();
961 if (trace || info->IsGCDerived())
962 CheckPolymorphicClass(info, trace);
963 }
964
960 { 965 {
961 CheckFieldsVisitor visitor(options_); 966 CheckFieldsVisitor visitor(options_);
962 if (visitor.ContainsInvalidFields(info)) 967 if (visitor.ContainsInvalidFields(info))
963 ReportClassContainsInvalidFields(info, &visitor.invalid_fields()); 968 ReportClassContainsInvalidFields(info, &visitor.invalid_fields());
964 } 969 }
965 970
966 if (info->IsGCDerived()) { 971 if (info->IsGCDerived()) {
967 972
968 if (!info->IsGCMixin()) { 973 if (!info->IsGCMixin()) {
969 CheckLeftMostDerived(info); 974 CheckLeftMostDerived(info);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
1003 1008
1004 // The GC infrastructure assumes that if the vtable of a polymorphic 1009 // The GC infrastructure assumes that if the vtable of a polymorphic
1005 // base-class is not initialized for a given object (ie, it is partially 1010 // base-class is not initialized for a given object (ie, it is partially
1006 // initialized) then the object does not need to be traced. Thus, we must 1011 // initialized) then the object does not need to be traced. Thus, we must
1007 // ensure that any polymorphic class with a trace method does not have any 1012 // ensure that any polymorphic class with a trace method does not have any
1008 // tractable fields that are initialized before we are sure that the vtable 1013 // tractable fields that are initialized before we are sure that the vtable
1009 // and the trace method are both defined. There are two cases that need to 1014 // and the trace method are both defined. There are two cases that need to
1010 // hold to satisfy that assumption: 1015 // hold to satisfy that assumption:
1011 // 1016 //
1012 // 1. If trace is virtual, then it must be defined in the left-most base. 1017 // 1. If trace is virtual, then it must be defined in the left-most base.
1013 // This ensures that if the vtable is initialized and it contains a pointer to 1018 // This ensures that if the vtable is initialized then it contains a pointer
1014 // the trace method. 1019 // to the trace method.
1015 // 1020 //
1016 // 2. If trace is non-virtual, then the trace method is defined and we must 1021 // 2. If trace is non-virtual, then the trace method is defined and we must
1017 // ensure that the left-most base defines a vtable. This ensures that the 1022 // ensure that the left-most base defines a vtable. This ensures that the
1018 // first thing to be initialized when constructing the object is the vtable 1023 // first thing to be initialized when constructing the object is the vtable
1019 // itself. 1024 // itself.
1020 void CheckPolymorphicClass(RecordInfo* info, CXXMethodDecl* trace) { 1025 void CheckPolymorphicClass(RecordInfo* info, CXXMethodDecl* trace) {
1021 CXXRecordDecl* left_most = info->record(); 1026 CXXRecordDecl* left_most = info->record();
1022 CXXRecordDecl::base_class_iterator it = left_most->bases_begin(); 1027 CXXRecordDecl::base_class_iterator it = left_most->bases_begin();
1023 CXXRecordDecl* left_most_base = 0; 1028 CXXRecordDecl* left_most_base = 0;
1024 while (it != left_most->bases_end()) { 1029 while (it != left_most->bases_end()) {
1025 left_most_base = it->getType()->getAsCXXRecordDecl(); 1030 left_most_base = it->getType()->getAsCXXRecordDecl();
1026 if (!left_most_base && it->getType()->isDependentType()) 1031 if (!left_most_base && it->getType()->isDependentType())
1027 left_most_base = GetDependentTemplatedDecl(*it->getType()); 1032 left_most_base = GetDependentTemplatedDecl(*it->getType());
1028 1033
1029 // TODO: Find a way to correctly check actual instantiations 1034 // TODO: Find a way to correctly check actual instantiations
1030 // for dependent types. The escape below will be hit, eg, when 1035 // for dependent types. The escape below will be hit, eg, when
1031 // we have a primary template with no definition and 1036 // we have a primary template with no definition and
1032 // specializations for each case (such as SupplementBase) in 1037 // specializations for each case (such as SupplementBase) in
1033 // which case we don't succeed in checking the required 1038 // which case we don't succeed in checking the required
1034 // properties. 1039 // properties.
1035 if (!left_most_base || !left_most_base->hasDefinition()) 1040 if (!left_most_base || !left_most_base->hasDefinition())
1036 return; 1041 return;
1037 1042
1038 StringRef name = left_most_base->getName(); 1043 StringRef name = left_most_base->getName();
1039 // We know GCMixin base defines virtual trace. 1044 // We know GCMixin base defines virtual trace.
1040 if (Config::IsGCMixinBase(name)) 1045 if (Config::IsGCMixinBase(name))
1041 return; 1046 return;
1042 1047
1043 // Stop with the left-most prior to a safe polymorphic base (a safe base 1048 // Stop with the left-most prior to a safe polymorphic base (a safe base
1044 // is non-polymorphic and contains no fields that need tracing). 1049 // is non-polymorphic and contains no fields).
1045 if (Config::IsSafePolymorphicBase(name)) 1050 if (Config::IsSafePolymorphicBase(name))
1046 break; 1051 break;
1047 1052
1048 left_most = left_most_base; 1053 left_most = left_most_base;
1049 it = left_most->bases_begin(); 1054 it = left_most->bases_begin();
1050 } 1055 }
1051 1056
1052 if (RecordInfo* left_most_info = cache_.Lookup(left_most)) { 1057 if (RecordInfo* left_most_info = cache_.Lookup(left_most)) {
1053 1058
1054 // Check condition (1): 1059 // Check condition (1):
1055 if (trace->isVirtual()) { 1060 if (trace && trace->isVirtual()) {
1056 if (CXXMethodDecl* trace = left_most_info->GetTraceMethod()) { 1061 if (CXXMethodDecl* trace = left_most_info->GetTraceMethod()) {
1057 if (trace->isVirtual()) 1062 if (trace->isVirtual())
1058 return; 1063 return;
1059 } 1064 }
1060 ReportBaseClassMustDeclareVirtualTrace(info, left_most); 1065 ReportBaseClassMustDeclareVirtualTrace(info, left_most);
1061 return; 1066 return;
1062 } 1067 }
1063 1068
1064 // Check condition (2): 1069 // Check condition (2):
1065 if (DeclaresVirtualMethods(info->record())) 1070 if (DeclaresVirtualMethods(left_most))
1066 return; 1071 return;
1067 if (left_most_base) { 1072 if (left_most_base) {
1068 ++it; // Get the base next to the "safe polymorphic base" 1073 ++it; // Get the base next to the "safe polymorphic base"
1069 if (it != left_most->bases_end()) { 1074 if (it != left_most->bases_end()) {
1070 if (CXXRecordDecl* next_base = it->getType()->getAsCXXRecordDecl()) { 1075 if (CXXRecordDecl* next_base = it->getType()->getAsCXXRecordDecl()) {
1071 if (CXXRecordDecl* next_left_most = GetLeftMostBase(next_base)) { 1076 if (CXXRecordDecl* next_left_most = GetLeftMostBase(next_base)) {
1072 if (DeclaresVirtualMethods(next_left_most)) 1077 if (DeclaresVirtualMethods(next_left_most))
1073 return; 1078 return;
1074 ReportLeftMostBaseMustBePolymorphic(info, next_left_most); 1079 ReportLeftMostBaseMustBePolymorphic(info, next_left_most);
1075 return; 1080 return;
(...skipping 792 matching lines...) Expand 10 before | Expand all | Expand 10 after
1868 1873
1869 private: 1874 private:
1870 BlinkGCPluginOptions options_; 1875 BlinkGCPluginOptions options_;
1871 }; 1876 };
1872 1877
1873 } // namespace 1878 } // namespace
1874 1879
1875 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( 1880 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X(
1876 "blink-gc-plugin", 1881 "blink-gc-plugin",
1877 "Check Blink GC invariants"); 1882 "Check Blink GC invariants");
OLDNEW
« no previous file with comments | « no previous file | tools/clang/blink_gc_plugin/tests/class_does_not_require_finalization.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698