| 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 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 381 if (call->getNumArgs() != 1) | 381 if (call->getNumArgs() != 1) |
| 382 return true; | 382 return true; |
| 383 Expr* arg = call->getArg(0); | 383 Expr* arg = call->getArg(0); |
| 384 | 384 |
| 385 if (UnresolvedMemberExpr* expr = dyn_cast<UnresolvedMemberExpr>(callee)) { | 385 if (UnresolvedMemberExpr* expr = dyn_cast<UnresolvedMemberExpr>(callee)) { |
| 386 // This could be a trace call of a base class, as explained in the | 386 // This could be a trace call of a base class, as explained in the |
| 387 // comments of CheckTraceBaseCall(). | 387 // comments of CheckTraceBaseCall(). |
| 388 if (CheckTraceBaseCall(call)) | 388 if (CheckTraceBaseCall(call)) |
| 389 return true; | 389 return true; |
| 390 | 390 |
| 391 // If we find a call to registerWeakMembers which is unresolved we | 391 if (expr->getMemberName().getAsString() == kRegisterWeakMembersName) |
| 392 // unsoundly consider all weak members as traced. | 392 MarkAllWeakMembersTraced(); |
| 393 // TODO: Find out how to validate weak member tracing for unresolved call. | |
| 394 if (expr->getMemberName().getAsString() == kRegisterWeakMembersName) { | |
| 395 for (RecordInfo::Fields::iterator it = info_->GetFields().begin(); | |
| 396 it != info_->GetFields().end(); | |
| 397 ++it) { | |
| 398 if (it->second.edge()->IsWeakMember()) | |
| 399 it->second.MarkTraced(); | |
| 400 } | |
| 401 } | |
| 402 | 393 |
| 403 QualType base = expr->getBaseType(); | 394 QualType base = expr->getBaseType(); |
| 404 if (!base->isPointerType()) | 395 if (!base->isPointerType()) |
| 405 return true; | 396 return true; |
| 406 CXXRecordDecl* decl = base->getPointeeType()->getAsCXXRecordDecl(); | 397 CXXRecordDecl* decl = base->getPointeeType()->getAsCXXRecordDecl(); |
| 407 if (decl) | 398 if (decl) |
| 408 CheckTraceFieldCall(expr->getMemberName().getAsString(), decl, arg); | 399 CheckTraceFieldCall(expr->getMemberName().getAsString(), decl, arg); |
| 409 if (Config::IsTraceImplName(expr->getMemberName().getAsString())) | 400 if (Config::IsTraceImplName(expr->getMemberName().getAsString())) |
| 410 delegates_to_traceimpl_ = true; | 401 delegates_to_traceimpl_ = true; |
| 411 return true; | 402 return true; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 447 if (!type) | 438 if (!type) |
| 448 return 0; | 439 return 0; |
| 449 | 440 |
| 450 return RecordInfo::GetDependentTemplatedDecl(*type); | 441 return RecordInfo::GetDependentTemplatedDecl(*type); |
| 451 } | 442 } |
| 452 | 443 |
| 453 void CheckCXXDependentScopeMemberExpr(CallExpr* call, | 444 void CheckCXXDependentScopeMemberExpr(CallExpr* call, |
| 454 CXXDependentScopeMemberExpr* expr) { | 445 CXXDependentScopeMemberExpr* expr) { |
| 455 string fn_name = expr->getMember().getAsString(); | 446 string fn_name = expr->getMember().getAsString(); |
| 456 | 447 |
| 457 // Check for VisitorDispatcher::trace(field) | 448 // Check for VisitorDispatcher::trace(field) and |
| 449 // VisitorDispatcher::registerWeakMembers. |
| 458 if (!expr->isImplicitAccess()) { | 450 if (!expr->isImplicitAccess()) { |
| 459 if (clang::DeclRefExpr* base_decl = | 451 if (clang::DeclRefExpr* base_decl = |
| 460 clang::dyn_cast<clang::DeclRefExpr>(expr->getBase())) { | 452 clang::dyn_cast<clang::DeclRefExpr>(expr->getBase())) { |
| 461 if (Config::IsVisitorDispatcherType(base_decl->getType()) && | 453 if (Config::IsVisitorDispatcherType(base_decl->getType())) { |
| 462 call->getNumArgs() == 1 && fn_name == kTraceName) { | 454 if (call->getNumArgs() == 1 && fn_name == kTraceName) { |
| 463 FindFieldVisitor finder; | 455 FindFieldVisitor finder; |
| 464 finder.TraverseStmt(call->getArg(0)); | 456 finder.TraverseStmt(call->getArg(0)); |
| 465 if (finder.field()) | 457 if (finder.field()) |
| 466 FoundField(finder.field()); | 458 FoundField(finder.field()); |
| 467 | 459 |
| 468 return; | 460 return; |
| 461 } else if (call->getNumArgs() == 1 && |
| 462 fn_name == kRegisterWeakMembersName) { |
| 463 MarkAllWeakMembersTraced(); |
| 464 } |
| 469 } | 465 } |
| 470 } | 466 } |
| 471 } | 467 } |
| 472 | 468 |
| 473 CXXRecordDecl* tmpl = GetDependentTemplatedDecl(expr); | 469 CXXRecordDecl* tmpl = GetDependentTemplatedDecl(expr); |
| 474 if (!tmpl) | 470 if (!tmpl) |
| 475 return; | 471 return; |
| 476 | 472 |
| 477 // Check for Super<T>::trace(visitor) | 473 // Check for Super<T>::trace(visitor) |
| 478 if (call->getNumArgs() == 1 && IsTraceCallName(fn_name)) { | 474 if (call->getNumArgs() == 1 && IsTraceCallName(fn_name)) { |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 689 break; | 685 break; |
| 690 } | 686 } |
| 691 } | 687 } |
| 692 } else { | 688 } else { |
| 693 RecordInfo::Fields::iterator it = info_->GetFields().find(field); | 689 RecordInfo::Fields::iterator it = info_->GetFields().find(field); |
| 694 if (it != info_->GetFields().end()) | 690 if (it != info_->GetFields().end()) |
| 695 MarkTraced(it); | 691 MarkTraced(it); |
| 696 } | 692 } |
| 697 } | 693 } |
| 698 | 694 |
| 695 void MarkAllWeakMembersTraced() { |
| 696 // If we find a call to registerWeakMembers which is unresolved we |
| 697 // unsoundly consider all weak members as traced. |
| 698 // TODO: Find out how to validate weak member tracing for unresolved call. |
| 699 for (auto& field : info_->GetFields()) { |
| 700 if (field.second.edge()->IsWeakMember()) |
| 701 field.second.MarkTraced(); |
| 702 } |
| 703 } |
| 704 |
| 699 CXXMethodDecl* trace_; | 705 CXXMethodDecl* trace_; |
| 700 RecordInfo* info_; | 706 RecordInfo* info_; |
| 701 RecordCache* cache_; | 707 RecordCache* cache_; |
| 702 bool delegates_to_traceimpl_; | 708 bool delegates_to_traceimpl_; |
| 703 }; | 709 }; |
| 704 | 710 |
| 705 // This visitor checks that the fields of a class and the fields of | 711 // This visitor checks that the fields of a class and the fields of |
| 706 // its part objects don't define GC roots. | 712 // its part objects don't define GC roots. |
| 707 class CheckGCRootsVisitor : public RecursiveEdgeVisitor { | 713 class CheckGCRootsVisitor : public RecursiveEdgeVisitor { |
| 708 public: | 714 public: |
| (...skipping 1338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2047 | 2053 |
| 2048 private: | 2054 private: |
| 2049 BlinkGCPluginOptions options_; | 2055 BlinkGCPluginOptions options_; |
| 2050 }; | 2056 }; |
| 2051 | 2057 |
| 2052 } // namespace | 2058 } // namespace |
| 2053 | 2059 |
| 2054 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( | 2060 static FrontendPluginRegistry::Add<BlinkGCPluginAction> X( |
| 2055 "blink-gc-plugin", | 2061 "blink-gc-plugin", |
| 2056 "Check Blink GC invariants"); | 2062 "Check Blink GC invariants"); |
| OLD | NEW |