| 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 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 393 | 393 |
| 394 CXXRecordDecl* GetDependentTemplatedDecl(CXXDependentScopeMemberExpr* expr) { | 394 CXXRecordDecl* GetDependentTemplatedDecl(CXXDependentScopeMemberExpr* expr) { |
| 395 NestedNameSpecifier* qual = expr->getQualifier(); | 395 NestedNameSpecifier* qual = expr->getQualifier(); |
| 396 if (!qual) | 396 if (!qual) |
| 397 return 0; | 397 return 0; |
| 398 | 398 |
| 399 const Type* type = qual->getAsType(); | 399 const Type* type = qual->getAsType(); |
| 400 if (!type) | 400 if (!type) |
| 401 return 0; | 401 return 0; |
| 402 | 402 |
| 403 const TemplateSpecializationType* tmpl_type = | 403 return RecordInfo::GetDependentTemplatedDecl(*type); |
| 404 type->getAs<TemplateSpecializationType>(); | |
| 405 if (!tmpl_type) | |
| 406 return 0; | |
| 407 | |
| 408 TemplateDecl* tmpl_decl = tmpl_type->getTemplateName().getAsTemplateDecl(); | |
| 409 if (!tmpl_decl) | |
| 410 return 0; | |
| 411 | |
| 412 return dyn_cast<CXXRecordDecl>(tmpl_decl->getTemplatedDecl()); | |
| 413 } | 404 } |
| 414 | 405 |
| 415 void CheckCXXDependentScopeMemberExpr(CallExpr* call, | 406 void CheckCXXDependentScopeMemberExpr(CallExpr* call, |
| 416 CXXDependentScopeMemberExpr* expr) { | 407 CXXDependentScopeMemberExpr* expr) { |
| 417 string fn_name = expr->getMember().getAsString(); | 408 string fn_name = expr->getMember().getAsString(); |
| 418 CXXRecordDecl* tmpl = GetDependentTemplatedDecl(expr); | 409 CXXRecordDecl* tmpl = GetDependentTemplatedDecl(expr); |
| 419 if (!tmpl) | 410 if (!tmpl) |
| 420 return; | 411 return; |
| 421 | 412 |
| 422 // Check for Super<T>::trace(visitor) | 413 // Check for Super<T>::trace(visitor) |
| (...skipping 612 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1035 // ensure that the left-most base defines a vtable. This ensures that the | 1026 // ensure that the left-most base defines a vtable. This ensures that the |
| 1036 // first thing to be initialized when constructing the object is the vtable | 1027 // first thing to be initialized when constructing the object is the vtable |
| 1037 // itself. | 1028 // itself. |
| 1038 void CheckPolymorphicClass(RecordInfo* info, CXXMethodDecl* trace) { | 1029 void CheckPolymorphicClass(RecordInfo* info, CXXMethodDecl* trace) { |
| 1039 CXXRecordDecl* left_most = info->record(); | 1030 CXXRecordDecl* left_most = info->record(); |
| 1040 CXXRecordDecl::base_class_iterator it = left_most->bases_begin(); | 1031 CXXRecordDecl::base_class_iterator it = left_most->bases_begin(); |
| 1041 CXXRecordDecl* left_most_base = 0; | 1032 CXXRecordDecl* left_most_base = 0; |
| 1042 while (it != left_most->bases_end()) { | 1033 while (it != left_most->bases_end()) { |
| 1043 left_most_base = it->getType()->getAsCXXRecordDecl(); | 1034 left_most_base = it->getType()->getAsCXXRecordDecl(); |
| 1044 if (!left_most_base && it->getType()->isDependentType()) | 1035 if (!left_most_base && it->getType()->isDependentType()) |
| 1045 left_most_base = GetDependentTemplatedDecl(*it->getType()); | 1036 left_most_base = RecordInfo::GetDependentTemplatedDecl(*it->getType()); |
| 1046 | 1037 |
| 1047 // TODO: Find a way to correctly check actual instantiations | 1038 // TODO: Find a way to correctly check actual instantiations |
| 1048 // for dependent types. The escape below will be hit, eg, when | 1039 // for dependent types. The escape below will be hit, eg, when |
| 1049 // we have a primary template with no definition and | 1040 // we have a primary template with no definition and |
| 1050 // specializations for each case (such as SupplementBase) in | 1041 // specializations for each case (such as SupplementBase) in |
| 1051 // which case we don't succeed in checking the required | 1042 // which case we don't succeed in checking the required |
| 1052 // properties. | 1043 // properties. |
| 1053 if (!left_most_base || !left_most_base->hasDefinition()) | 1044 if (!left_most_base || !left_most_base->hasDefinition()) |
| 1054 return; | 1045 return; |
| 1055 | 1046 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1096 } | 1087 } |
| 1097 } | 1088 } |
| 1098 ReportLeftMostBaseMustBePolymorphic(info, left_most); | 1089 ReportLeftMostBaseMustBePolymorphic(info, left_most); |
| 1099 } | 1090 } |
| 1100 } | 1091 } |
| 1101 | 1092 |
| 1102 CXXRecordDecl* GetLeftMostBase(CXXRecordDecl* left_most) { | 1093 CXXRecordDecl* GetLeftMostBase(CXXRecordDecl* left_most) { |
| 1103 CXXRecordDecl::base_class_iterator it = left_most->bases_begin(); | 1094 CXXRecordDecl::base_class_iterator it = left_most->bases_begin(); |
| 1104 while (it != left_most->bases_end()) { | 1095 while (it != left_most->bases_end()) { |
| 1105 if (it->getType()->isDependentType()) | 1096 if (it->getType()->isDependentType()) |
| 1106 left_most = GetDependentTemplatedDecl(*it->getType()); | 1097 left_most = RecordInfo::GetDependentTemplatedDecl(*it->getType()); |
| 1107 else | 1098 else |
| 1108 left_most = it->getType()->getAsCXXRecordDecl(); | 1099 left_most = it->getType()->getAsCXXRecordDecl(); |
| 1109 if (!left_most || !left_most->hasDefinition()) | 1100 if (!left_most || !left_most->hasDefinition()) |
| 1110 return 0; | 1101 return 0; |
| 1111 it = left_most->bases_begin(); | 1102 it = left_most->bases_begin(); |
| 1112 } | 1103 } |
| 1113 return left_most; | 1104 return left_most; |
| 1114 } | 1105 } |
| 1115 | 1106 |
| 1116 bool DeclaresVirtualMethods(CXXRecordDecl* decl) { | 1107 bool DeclaresVirtualMethods(CXXRecordDecl* decl) { |
| 1117 CXXRecordDecl::method_iterator it = decl->method_begin(); | 1108 CXXRecordDecl::method_iterator it = decl->method_begin(); |
| 1118 for (; it != decl->method_end(); ++it) | 1109 for (; it != decl->method_end(); ++it) |
| 1119 if (it->isVirtual() && !it->isPure()) | 1110 if (it->isVirtual() && !it->isPure()) |
| 1120 return true; | 1111 return true; |
| 1121 return false; | 1112 return false; |
| 1122 } | 1113 } |
| 1123 | 1114 |
| 1124 void CheckLeftMostDerived(RecordInfo* info) { | 1115 void CheckLeftMostDerived(RecordInfo* info) { |
| 1125 CXXRecordDecl* left_most = info->record(); | 1116 CXXRecordDecl* left_most = GetLeftMostBase(info->record()); |
| 1126 CXXRecordDecl::base_class_iterator it = left_most->bases_begin(); | 1117 if (!left_most) |
| 1127 while (it != left_most->bases_end()) { | 1118 return; |
| 1128 left_most = it->getType()->getAsCXXRecordDecl(); | |
| 1129 it = left_most->bases_begin(); | |
| 1130 } | |
| 1131 if (!Config::IsGCBase(left_most->getName())) | 1119 if (!Config::IsGCBase(left_most->getName())) |
| 1132 ReportClassMustLeftMostlyDeriveGC(info); | 1120 ReportClassMustLeftMostlyDeriveGC(info); |
| 1133 } | 1121 } |
| 1134 | 1122 |
| 1135 void CheckDispatch(RecordInfo* info) { | 1123 void CheckDispatch(RecordInfo* info) { |
| 1136 bool finalized = info->IsGCFinalized(); | 1124 bool finalized = info->IsGCFinalized(); |
| 1137 CXXMethodDecl* trace_dispatch = info->GetTraceDispatchMethod(); | 1125 CXXMethodDecl* trace_dispatch = info->GetTraceDispatchMethod(); |
| 1138 CXXMethodDecl* finalize_dispatch = info->GetFinalizeDispatchMethod(); | 1126 CXXMethodDecl* finalize_dispatch = info->GetFinalizeDispatchMethod(); |
| 1139 if (!trace_dispatch && !finalize_dispatch) | 1127 if (!trace_dispatch && !finalize_dispatch) |
| 1140 return; | 1128 return; |
| (...skipping 746 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1887 | 1875 |
| 1888 private: | 1876 private: |
| 1889 BlinkGCPluginOptions options_; | 1877 BlinkGCPluginOptions options_; |
| 1890 }; | 1878 }; |
| 1891 | 1879 |
| 1892 } // namespace | 1880 } // namespace |
| 1893 | 1881 |
| 1894 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( | 1882 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( |
| 1895 "blink-gc-plugin", | 1883 "blink-gc-plugin", |
| 1896 "Check Blink GC invariants"); | 1884 "Check Blink GC invariants"); |
| OLD | NEW |