| 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 |