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