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 "Config.h" | 11 #include "Config.h" |
12 #include "JsonWriter.h" | 12 #include "JsonWriter.h" |
13 #include "RecordInfo.h" | 13 #include "RecordInfo.h" |
14 | 14 |
15 #include "clang/AST/AST.h" | 15 #include "clang/AST/AST.h" |
16 #include "clang/AST/ASTConsumer.h" | 16 #include "clang/AST/ASTConsumer.h" |
17 #include "clang/AST/RecursiveASTVisitor.h" | 17 #include "clang/AST/RecursiveASTVisitor.h" |
18 #include "clang/Frontend/CompilerInstance.h" | 18 #include "clang/Frontend/CompilerInstance.h" |
19 #include "clang/Frontend/FrontendPluginRegistry.h" | 19 #include "clang/Frontend/FrontendPluginRegistry.h" |
20 #include "clang/Sema/Sema.h" | |
21 | 20 |
22 using namespace clang; | 21 using namespace clang; |
23 using std::string; | 22 using std::string; |
24 | 23 |
25 namespace { | 24 namespace { |
26 | 25 |
27 const char kClassMustLeftMostlyDeriveGC[] = | 26 const char kClassMustLeftMostlyDeriveGC[] = |
28 "[blink-gc] Class %0 must derive its GC base in the left-most position."; | 27 "[blink-gc] Class %0 must derive its GC base in the left-most position."; |
29 | 28 |
30 const char kClassRequiresTraceMethod[] = | 29 const char kClassRequiresTraceMethod[] = |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 " must be polymorphic."; | 137 " must be polymorphic."; |
139 | 138 |
140 const char kBaseClassMustDeclareVirtualTrace[] = | 139 const char kBaseClassMustDeclareVirtualTrace[] = |
141 "[blink-gc] Left-most base class %0 of derived class %1" | 140 "[blink-gc] Left-most base class %0 of derived class %1" |
142 " must define a virtual trace method."; | 141 " must define a virtual trace method."; |
143 | 142 |
144 const char kClassMustDeclareGCMixinTraceMethod[] = | 143 const char kClassMustDeclareGCMixinTraceMethod[] = |
145 "[blink-gc] Class %0 which inherits from GarbageCollectedMixin must" | 144 "[blink-gc] Class %0 which inherits from GarbageCollectedMixin must" |
146 " locally declare and override trace(Visitor*)"; | 145 " locally declare and override trace(Visitor*)"; |
147 | 146 |
148 // Use a local RAV implementation to simply collect all FunctionDecls marked for | |
149 // late template parsing. This happens with the flag -fdelayed-template-parsing, | |
150 // which is on by default in MSVC-compatible mode. | |
151 std::set<FunctionDecl*> GetLateParsedFunctionDecls(TranslationUnitDecl* decl) { | |
152 struct Visitor : public RecursiveASTVisitor<Visitor> { | |
153 bool VisitFunctionDecl(FunctionDecl* function_decl) { | |
154 if (function_decl->isLateTemplateParsed()) | |
155 late_parsed_decls.insert(function_decl); | |
156 return true; | |
157 } | |
158 | |
159 std::set<FunctionDecl*> late_parsed_decls; | |
160 } v; | |
161 v.TraverseDecl(decl); | |
162 return v.late_parsed_decls; | |
163 } | |
164 | |
165 struct BlinkGCPluginOptions { | 147 struct BlinkGCPluginOptions { |
166 BlinkGCPluginOptions() | 148 BlinkGCPluginOptions() |
167 : enable_oilpan(false) | 149 : enable_oilpan(false) |
168 , dump_graph(false) | 150 , dump_graph(false) |
169 , warn_raw_ptr(false) | 151 , warn_raw_ptr(false) |
170 , warn_unneeded_finalizer(false) {} | 152 , warn_unneeded_finalizer(false) {} |
171 bool enable_oilpan; | 153 bool enable_oilpan; |
172 bool dump_graph; | 154 bool dump_graph; |
173 bool warn_raw_ptr; | 155 bool warn_raw_ptr; |
174 bool warn_unneeded_finalizer; | 156 bool warn_unneeded_finalizer; |
(...skipping 853 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1028 DiagnosticsEngine::Note, kOverriddenNonVirtualTraceNote); | 1010 DiagnosticsEngine::Note, kOverriddenNonVirtualTraceNote); |
1029 diag_manual_dispatch_method_note_ = diagnostic_.getCustomDiagID( | 1011 diag_manual_dispatch_method_note_ = diagnostic_.getCustomDiagID( |
1030 DiagnosticsEngine::Note, kManualDispatchMethodNote); | 1012 DiagnosticsEngine::Note, kManualDispatchMethodNote); |
1031 } | 1013 } |
1032 | 1014 |
1033 void HandleTranslationUnit(ASTContext& context) override { | 1015 void HandleTranslationUnit(ASTContext& context) override { |
1034 // Don't run the plugin if the compilation unit is already invalid. | 1016 // Don't run the plugin if the compilation unit is already invalid. |
1035 if (diagnostic_.hasErrorOccurred()) | 1017 if (diagnostic_.hasErrorOccurred()) |
1036 return; | 1018 return; |
1037 | 1019 |
1038 ParseFunctionTemplates(context.getTranslationUnitDecl()); | |
1039 | |
1040 CollectVisitor visitor; | 1020 CollectVisitor visitor; |
1041 visitor.TraverseDecl(context.getTranslationUnitDecl()); | 1021 visitor.TraverseDecl(context.getTranslationUnitDecl()); |
1042 | 1022 |
1043 if (options_.dump_graph) { | 1023 if (options_.dump_graph) { |
1044 std::error_code err; | 1024 std::error_code err; |
1045 // TODO: Make createDefaultOutputFile or a shorter createOutputFile work. | 1025 // TODO: Make createDefaultOutputFile or a shorter createOutputFile work. |
1046 json_ = JsonWriter::from(instance_.createOutputFile( | 1026 json_ = JsonWriter::from(instance_.createOutputFile( |
1047 "", // OutputPath | 1027 "", // OutputPath |
1048 err, // Errors | 1028 err, // Errors |
1049 true, // Binary | 1029 true, // Binary |
(...skipping 26 matching lines...) Expand all Loading... |
1076 CheckTracingMethod(*it); | 1056 CheckTracingMethod(*it); |
1077 } | 1057 } |
1078 | 1058 |
1079 if (json_) { | 1059 if (json_) { |
1080 json_->CloseList(); | 1060 json_->CloseList(); |
1081 delete json_; | 1061 delete json_; |
1082 json_ = 0; | 1062 json_ = 0; |
1083 } | 1063 } |
1084 } | 1064 } |
1085 | 1065 |
1086 void ParseFunctionTemplates(TranslationUnitDecl* decl) { | |
1087 if (!instance_.getLangOpts().DelayedTemplateParsing) | |
1088 return; // Nothing to do. | |
1089 | |
1090 std::set<FunctionDecl*> late_parsed_decls = | |
1091 GetLateParsedFunctionDecls(decl); | |
1092 clang::Sema& sema = instance_.getSema(); | |
1093 | |
1094 for (const FunctionDecl* fd : late_parsed_decls) { | |
1095 assert(fd->isLateTemplateParsed()); | |
1096 | |
1097 if (!Config::IsTraceMethod(fd)) | |
1098 continue; | |
1099 | |
1100 if (instance_.getSourceManager().isInSystemHeader( | |
1101 instance_.getSourceManager().getSpellingLoc(fd->getLocation()))) | |
1102 continue; | |
1103 | |
1104 // Force parsing and AST building of the yet-uninstantiated function | |
1105 // template trace method bodies. | |
1106 clang::LateParsedTemplate* lpt = sema.LateParsedTemplateMap[fd]; | |
1107 sema.LateTemplateParser(sema.OpaqueParser, *lpt); | |
1108 } | |
1109 } | |
1110 | |
1111 // Main entry for checking a record declaration. | 1066 // Main entry for checking a record declaration. |
1112 void CheckRecord(RecordInfo* info) { | 1067 void CheckRecord(RecordInfo* info) { |
1113 if (IsIgnored(info)) | 1068 if (IsIgnored(info)) |
1114 return; | 1069 return; |
1115 | 1070 |
1116 CXXRecordDecl* record = info->record(); | 1071 CXXRecordDecl* record = info->record(); |
1117 | 1072 |
1118 // TODO: what should we do to check unions? | 1073 // TODO: what should we do to check unions? |
1119 if (record->isUnion()) | 1074 if (record->isUnion()) |
1120 return; | 1075 return; |
(...skipping 978 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2099 | 2054 |
2100 private: | 2055 private: |
2101 BlinkGCPluginOptions options_; | 2056 BlinkGCPluginOptions options_; |
2102 }; | 2057 }; |
2103 | 2058 |
2104 } // namespace | 2059 } // namespace |
2105 | 2060 |
2106 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( | 2061 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( |
2107 "blink-gc-plugin", | 2062 "blink-gc-plugin", |
2108 "Check Blink GC invariants"); | 2063 "Check Blink GC invariants"); |
OLD | NEW |