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 |