OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 #include "CheckTraceVisitor.h" | 5 #include "CheckTraceVisitor.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "Config.h" | 9 #include "Config.h" |
10 | 10 |
11 using namespace clang; | 11 using namespace clang; |
12 | 12 |
13 CheckTraceVisitor::CheckTraceVisitor(CXXMethodDecl* trace, | 13 CheckTraceVisitor::CheckTraceVisitor(CXXMethodDecl* trace, |
14 RecordInfo* info, | 14 RecordInfo* info, |
15 RecordCache* cache) | 15 RecordCache* cache) |
16 : trace_(trace), | 16 : trace_(trace), info_(info), cache_(cache) {} |
17 info_(info), | |
18 cache_(cache), | |
19 delegates_to_traceimpl_(false) { | |
20 } | |
21 | |
22 bool CheckTraceVisitor::delegates_to_traceimpl() const { | |
23 return delegates_to_traceimpl_; | |
24 } | |
25 | 17 |
26 bool CheckTraceVisitor::VisitMemberExpr(MemberExpr* member) { | 18 bool CheckTraceVisitor::VisitMemberExpr(MemberExpr* member) { |
27 // In weak callbacks, consider any occurrence as a correct usage. | 19 // In weak callbacks, consider any occurrence as a correct usage. |
28 // TODO: We really want to require that isAlive is checked on manually | 20 // TODO: We really want to require that isAlive is checked on manually |
29 // processed weak fields. | 21 // processed weak fields. |
30 if (IsWeakCallback()) { | 22 if (IsWeakCallback()) { |
31 if (FieldDecl* field = dyn_cast<FieldDecl>(member->getMemberDecl())) | 23 if (FieldDecl* field = dyn_cast<FieldDecl>(member->getMemberDecl())) |
32 FoundField(field); | 24 FoundField(field); |
33 } | 25 } |
34 return true; | 26 return true; |
(...skipping 30 matching lines...) Expand all Loading... |
65 | 57 |
66 if (expr->getMemberName().getAsString() == kRegisterWeakMembersName) | 58 if (expr->getMemberName().getAsString() == kRegisterWeakMembersName) |
67 MarkAllWeakMembersTraced(); | 59 MarkAllWeakMembersTraced(); |
68 | 60 |
69 QualType base = expr->getBaseType(); | 61 QualType base = expr->getBaseType(); |
70 if (!base->isPointerType()) | 62 if (!base->isPointerType()) |
71 return true; | 63 return true; |
72 CXXRecordDecl* decl = base->getPointeeType()->getAsCXXRecordDecl(); | 64 CXXRecordDecl* decl = base->getPointeeType()->getAsCXXRecordDecl(); |
73 if (decl) | 65 if (decl) |
74 CheckTraceFieldCall(expr->getMemberName().getAsString(), decl, arg); | 66 CheckTraceFieldCall(expr->getMemberName().getAsString(), decl, arg); |
75 if (Config::IsTraceImplName(expr->getMemberName().getAsString())) | |
76 delegates_to_traceimpl_ = true; | |
77 return true; | 67 return true; |
78 } | 68 } |
79 | 69 |
80 if (CXXMemberCallExpr* expr = dyn_cast<CXXMemberCallExpr>(call)) { | 70 if (CXXMemberCallExpr* expr = dyn_cast<CXXMemberCallExpr>(call)) { |
81 if (CheckTraceFieldMemberCall(expr) || CheckRegisterWeakMembers(expr)) | 71 if (CheckTraceFieldMemberCall(expr) || CheckRegisterWeakMembers(expr)) |
82 return true; | 72 return true; |
83 | 73 |
84 if (Config::IsTraceImplName(expr->getMethodDecl()->getNameAsString())) { | |
85 delegates_to_traceimpl_ = true; | |
86 return true; | |
87 } | |
88 } | 74 } |
89 | 75 |
90 CheckTraceBaseCall(call); | 76 CheckTraceBaseCall(call); |
91 return true; | 77 return true; |
92 } | 78 } |
93 | 79 |
94 bool CheckTraceVisitor::IsTraceCallName(const std::string& name) { | 80 bool CheckTraceVisitor::IsTraceCallName(const std::string& name) { |
95 if (trace_->getName() == kTraceImplName) | |
96 return name == kTraceName; | |
97 if (trace_->getName() == kTraceAfterDispatchImplName) | |
98 return name == kTraceAfterDispatchName; | |
99 // Currently, a manually dispatched class cannot have mixin bases (having | 81 // Currently, a manually dispatched class cannot have mixin bases (having |
100 // one would add a vtable which we explicitly check against). This means | 82 // one would add a vtable which we explicitly check against). This means |
101 // that we can only make calls to a trace method of the same name. Revisit | 83 // that we can only make calls to a trace method of the same name. Revisit |
102 // this if our mixin/vtable assumption changes. | 84 // this if our mixin/vtable assumption changes. |
103 return name == trace_->getName(); | 85 return name == trace_->getName(); |
104 } | 86 } |
105 | 87 |
106 CXXRecordDecl* CheckTraceVisitor::GetDependentTemplatedDecl( | 88 CXXRecordDecl* CheckTraceVisitor::GetDependentTemplatedDecl( |
107 CXXDependentScopeMemberExpr* expr) { | 89 CXXDependentScopeMemberExpr* expr) { |
108 NestedNameSpecifier* qual = expr->getQualifier(); | 90 NestedNameSpecifier* qual = expr->getQualifier(); |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
225 const Type* type = callee->getQualifier()->getAsType(); | 207 const Type* type = callee->getQualifier()->getAsType(); |
226 if (!type) | 208 if (!type) |
227 return false; | 209 return false; |
228 | 210 |
229 callee_record = type->getAsCXXRecordDecl(); | 211 callee_record = type->getAsCXXRecordDecl(); |
230 func_name = trace_decl->getName(); | 212 func_name = trace_decl->getName(); |
231 } else if (UnresolvedMemberExpr* callee = | 213 } else if (UnresolvedMemberExpr* callee = |
232 dyn_cast<UnresolvedMemberExpr>(call->getCallee())) { | 214 dyn_cast<UnresolvedMemberExpr>(call->getCallee())) { |
233 // Callee part may become unresolved if the type of the argument | 215 // Callee part may become unresolved if the type of the argument |
234 // ("visitor") is a template parameter and the called function is | 216 // ("visitor") is a template parameter and the called function is |
235 // overloaded (i.e. trace(Visitor*) and | 217 // overloaded. |
236 // trace(InlinedGlobalMarkingVisitor)). | |
237 // | 218 // |
238 // Here, we try to find a function that looks like trace() from the | 219 // Here, we try to find a function that looks like trace() from the |
239 // candidate overloaded functions, and if we find one, we assume it is | 220 // candidate overloaded functions, and if we find one, we assume it is |
240 // called here. | 221 // called here. |
241 | 222 |
242 CXXMethodDecl* trace_decl = nullptr; | 223 CXXMethodDecl* trace_decl = nullptr; |
243 for (NamedDecl* named_decl : callee->decls()) { | 224 for (NamedDecl* named_decl : callee->decls()) { |
244 if (CXXMethodDecl* method_decl = dyn_cast<CXXMethodDecl>(named_decl)) { | 225 if (CXXMethodDecl* method_decl = dyn_cast<CXXMethodDecl>(named_decl)) { |
245 if (Config::IsTraceMethod(method_decl)) { | 226 if (Config::IsTraceMethod(method_decl)) { |
246 trace_decl = method_decl; | 227 trace_decl = method_decl; |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
344 // The second template argument is the callback method. | 325 // The second template argument is the callback method. |
345 if (args.size() > 1 && | 326 if (args.size() > 1 && |
346 args[1].getKind() == TemplateArgument::Declaration) { | 327 args[1].getKind() == TemplateArgument::Declaration) { |
347 if (FunctionDecl* callback = | 328 if (FunctionDecl* callback = |
348 dyn_cast<FunctionDecl>(args[1].getAsDecl())) { | 329 dyn_cast<FunctionDecl>(args[1].getAsDecl())) { |
349 if (callback->hasBody()) { | 330 if (callback->hasBody()) { |
350 CheckTraceVisitor nested_visitor(nullptr, info_, nullptr); | 331 CheckTraceVisitor nested_visitor(nullptr, info_, nullptr); |
351 nested_visitor.TraverseStmt(callback->getBody()); | 332 nested_visitor.TraverseStmt(callback->getBody()); |
352 } | 333 } |
353 } | 334 } |
| 335 // TODO: mark all WeakMember<>s as traced even if |
| 336 // the body isn't available? |
354 } | 337 } |
355 } | 338 } |
356 return true; | 339 return true; |
357 } | 340 } |
358 | 341 |
359 bool CheckTraceVisitor::IsWeakCallback() const { | 342 bool CheckTraceVisitor::IsWeakCallback() const { |
360 return !trace_; | 343 return !trace_; |
361 } | 344 } |
362 | 345 |
363 void CheckTraceVisitor::MarkTraced(RecordInfo::Fields::iterator it) { | 346 void CheckTraceVisitor::MarkTraced(RecordInfo::Fields::iterator it) { |
(...skipping 26 matching lines...) Expand all Loading... |
390 | 373 |
391 void CheckTraceVisitor::MarkAllWeakMembersTraced() { | 374 void CheckTraceVisitor::MarkAllWeakMembersTraced() { |
392 // If we find a call to registerWeakMembers which is unresolved we | 375 // If we find a call to registerWeakMembers which is unresolved we |
393 // unsoundly consider all weak members as traced. | 376 // unsoundly consider all weak members as traced. |
394 // TODO: Find out how to validate weak member tracing for unresolved call. | 377 // TODO: Find out how to validate weak member tracing for unresolved call. |
395 for (auto& field : info_->GetFields()) { | 378 for (auto& field : info_->GetFields()) { |
396 if (field.second.edge()->IsWeakMember()) | 379 if (field.second.edge()->IsWeakMember()) |
397 field.second.MarkTraced(); | 380 field.second.MarkTraced(); |
398 } | 381 } |
399 } | 382 } |
OLD | NEW |